diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt
index 22601b643a..694fe3e289 100644
--- a/.ci/dependencies_msys.txt
+++ b/.ci/dependencies_msys.txt
@@ -12,3 +12,4 @@ libslirp
fluidsynth
qt5-static
qt5-translations
+vulkan-headers
diff --git a/.editorconfig b/.editorconfig
index 29d9ac0bad..fa7defd570 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,34 +5,11 @@ indent_style = space
indent_size = 4
tab_width = 4
-# Disabled for now since not all editors support setting a tab_width value different from indent_size
-# Relevant VSCode extension issue: https://github.com/editorconfig/editorconfig-vscode/issues/190
-# [*.rc]
-# indent_style = space
-# indent_size = 4
-# tab_width = 4
-
-# [Makefile.*]
-# indent_style = space
-# indent_size = 4
-# tab_width = 4
-
[*.manifest]
-indent_style = space
indent_size = 2
[*.yml]
-indent_style = space
indent_size = 2
-[**/CMakeLists.txt]
-indent_style = space
-indent_size = 4
-
-[*.cmake]
-indent_style = space
-indent_size = 4
-
-[*.json]
-indent_style = space
-indent_size = 4
+[*.ui]
+indent_size = 1
diff --git a/.gitattributes b/.gitattributes
index 32eb262c92..9b39a29c0e 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3,12 +3,28 @@
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
+# Code
*.c text
*.cc text
*.cpp text
*.h text
*.hpp text
+
+# CMake scripts
+CMakeLists.txt text
+*.cmake text
+
+# Windows resource scripts and manifests
*.rc text
+*.manifest text
+
+# Translation files
+*.po text
+
+# Qt XML files
+*.ui text
+*.ts text
+*.qrc text
# Declare files that will always have CRLF line endings on checkout.
diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml
deleted file mode 100644
index 2a22a19cfa..0000000000
--- a/.github/workflows/c-cpp.yml
+++ /dev/null
@@ -1,116 +0,0 @@
-name: MSYS2 Makefile (Windows, Legacy)
-
-on:
-
- push:
- paths:
- - src/**
- - .github/workflows/c-cpp.yml
- - "!**/CMakeLists.txt"
-
- pull_request:
- paths:
- - src/**
- - .github/workflows/c-cpp.yml
- - "!**/CMakeLists.txt"
-
-jobs:
- msys2:
- # Negative condition disables the job
- if: false
- name: "Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
-
- runs-on: windows-2022
-
- defaults:
- run:
- shell: msys2 {0}
-
- strategy:
- fail-fast: true
- matrix:
- build:
-# - name: Regular
-# debug: n
-# dev: n
- - name: Debug
- debug: y
- dev: n
- slug: -Debug
- - name: Dev
- debug: y
- dev: y
- slug: -Dev
- dynarec:
- - name: ODR
- new: n
- slug: -ODR
- - name: NDR
- new: y
- slug: -NDR
- environment:
-# - msystem: MSYS
-# clang: n
-# x64: y
- - msystem: MINGW32
- prefix: mingw-w64-i686
- clang: n
- x64: n
- - msystem: MINGW64
- prefix: mingw-w64-x86_64
- clang: n
- x64: y
-# - msystem: CLANG32
-# prefix: mingw-w64-clang-i686
-# clang: y
-# x64: n
-# - msystem: CLANG64
-# prefix: mingw-w64-clang-x86_64
-# clang: y
-# x64: y
- - msystem: UCRT64
- prefix: mingw-w64-ucrt-x86_64
- clang: n
- x64: y
-
- steps:
- - name: Prepare MSYS2 environment
- uses: msys2/setup-msys2@v2
- with:
- release: false
- update: true
- msystem: ${{ matrix.environment.msystem }}
- install: >-
- make
- pacboy: >-
- gcc:p
- clang:p
- pkg-config:p
- freetype:p
- SDL2:p
- zlib:p
- libpng:p
- openal:p
- rtmidi:p
- libslirp:p
- fluidsynth:p
- libvncserver:p
-
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: make
- run: >-
- make -fwin/Makefile.mingw -j
- DEV_BUILD=${{ matrix.build.dev }}
- DEBUG=${{ matrix.build.debug }}
- NEW_DYNAREC=${{ matrix.dynarec.new }}
- CLANG=${{ matrix.environment.clang }}
- X64=${{ matrix.environment.x64 }}
- working-directory: ./src
-
- - name: Upload artifact
- uses: actions/upload-artifact@v3
- with:
- name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}'
- path: src/86Box.exe
diff --git a/.github/workflows/cmake_linux.yml b/.github/workflows/cmake_linux.yml
index c09789bfc7..f1ef973c49 100644
--- a/.github/workflows/cmake_linux.yml
+++ b/.github/workflows/cmake_linux.yml
@@ -8,7 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- - .github/workflows/cmake.yml
+ - .github/workflows/cmake_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -19,7 +19,7 @@ on:
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- - .github/workflows/cmake.yml
+ - .github/workflows/cmake_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -80,7 +80,6 @@ jobs:
libopenal-dev
libslirp-dev
libfluidsynth-dev
- libvncserver-dev
${{ matrix.ui.packages }}
- name: Checkout repository
@@ -89,7 +88,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
- uses: SonarSource/sonarcloud-github-c-cpp@v2
+ uses: SonarSource/sonarcloud-github-c-cpp@5c3c39143e381909307f6903f13774b275ed956d
- name: Configure CMake
run: >-
@@ -116,7 +115,7 @@ jobs:
cmake --install build
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy-x86_64-gha${{ github.run_number }}'
path: build/artifacts/**
diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml
index 7a6edcde98..045626cd16 100644
--- a/.github/workflows/cmake_macos.yml
+++ b/.github/workflows/cmake_macos.yml
@@ -8,7 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- - .github/workflows/cmake.yml
+ - .github/workflows/cmake_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -19,7 +19,7 @@ on:
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- - .github/workflows/cmake.yml
+ - .github/workflows/cmake_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -76,13 +76,10 @@ jobs:
run: >-
brew install
ninja
- freetype
sdl2
- libpng
rtmidi
openal-soft
fluidsynth
- libvncserver
${{ matrix.ui.packages }}
- name: Checkout repository
@@ -91,7 +88,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
- uses: SonarSource/sonarcloud-github-c-cpp@v2
+ uses: SonarSource/sonarcloud-github-c-cpp@5c3c39143e381909307f6903f13774b275ed956d
- name: Configure CMake
run: >-
@@ -121,7 +118,106 @@ jobs:
cmake --install build
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-macOS-x86_64-gha${{ github.run_number }}'
path: build/artifacts/**
+
+ macos14-arm64:
+ name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, arm64"
+
+ runs-on: macos-14
+
+# env:
+# BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
+
+ strategy:
+ fail-fast: true
+ matrix:
+ build:
+# - name: Regular
+# preset: regular
+ - name: Debug
+ preset: debug
+ slug: -Debug
+ - name: Dev
+ preset: experimental
+ slug: -Dev
+ dynarec:
+# - name: ODR
+# new: off
+# slug: -ODR
+ - name: NDR
+ new: on
+ slug: -NDR
+ ui:
+ - name: SDL GUI
+ qt: off
+ static: on
+ src-packages: >-
+ libsndfile
+ - name: Qt GUI
+ qt: on
+ slug: -Qt
+ packages: >-
+ qt@5
+ src-packages: >-
+ libsndfile
+
+ steps:
+ - name: Install source dependencies
+ run: >-
+ brew reinstall -s
+ ${{ matrix.ui.src-packages }}
+
+ - name: Install dependencies
+ run: >-
+ brew install
+ ninja
+ sdl2
+ rtmidi
+ openal-soft
+ fluidsynth
+ libslirp
+ ${{ matrix.ui.packages }}
+
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
+
+# - name: Install sonar-scanner and build-wrapper
+# uses: SonarSource/sonarcloud-github-c-cpp@5c3c39143e381909307f6903f13774b275ed956d
+
+ - name: Configure CMake
+ run: >-
+ cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
+ --toolchain ./cmake/llvm-macos-aarch64.cmake
+ -D NEW_DYNAREC=${{ matrix.dynarec.new }}
+ -D CMAKE_INSTALL_PREFIX=./build/artifacts
+ -D QT=${{ matrix.ui.qt }}
+ -D Qt5_ROOT=$(brew --prefix qt@5)
+ -D Qt5LinguistTools_ROOT=$(brew --prefix qt@5)
+ -D OpenAL_ROOT=$(brew --prefix openal-soft)
+
+ - name: Build
+ run: |
+ cmake --build build
+
+# - name: Run sonar-scanner
+# if: 0
+# env:
+# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
+# run: |
+# sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
+
+ - name: Generate package
+ run: |
+ cmake --install build
+
+ - name: Upload artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-macOS-arm64-gha${{ github.run_number }}'
+ path: build/artifacts/**
diff --git a/.github/workflows/cmake_windows_llvm.yml b/.github/workflows/cmake_windows_llvm.yml
deleted file mode 100644
index a49f9488a1..0000000000
--- a/.github/workflows/cmake_windows_llvm.yml
+++ /dev/null
@@ -1,163 +0,0 @@
-name: CMake (Windows, vcpkg/LLVM)
-
-on:
-
- push:
- paths:
- - src/**
- - cmake/**
- - "**/CMakeLists.txt"
- - "CMakePresets.json"
- - .github/workflows/cmake.yml
- - vcpkg.json
- - "!**/Makefile*"
-
- pull_request:
- paths:
- - src/**
- - cmake/**
- - "**/CMakeLists.txt"
- - "CMakePresets.json"
- - .github/workflows/**
- - .github/workflows/cmake.yml
- - vcpkg.json
- - "!**/Makefile*"
-
-jobs:
-
- llvm-windows:
- name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.target.name }}"
- if: 0
-
- runs-on: windows-2022
-
- env:
- BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
- VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite'
-
- strategy:
- fail-fast: true
- matrix:
- build:
-# - name: Regular
-# preset: regular
- - name: Debug
- preset: debug
- slug: -Debug
- - name: Dev
- preset: experimental
- slug: -Dev
- dynarec:
- - name: ODR
- new: off
- slug: -ODR
- - name: NDR
- new: on
- slug: -NDR
- ui:
- - name: Win32 GUI
- qt: off
- - name: Qt GUI
- qt: on
- slug: -Qt
- target:
- - name: x86
- triplet: x86-windows-static
- toolchain: ./cmake/llvm-win32-i686.cmake
- vcvars: x64_x86
- - name: x64
- triplet: x64-windows-static
- toolchain: ./cmake/llvm-win32-x86_64.cmake
- vcvars: x64
-# - name: ARM
-# triplet: arm-windows-static
-# toolchain: ./cmake/llvm-win32-arm.cmake
-# vcvars: x64_arm
- - name: ARM64
- triplet: arm64-windows-static
- toolchain: ./cmake/llvm-win32-aarch64.cmake
- vcvars: x64_arm64
- exclude:
- - dynarec:
- new: off
- target:
- name: ARM64
-
- steps:
- - name: Prepare VS environment
- uses: ilammy/msvc-dev-cmd@v1
- with:
- arch: ${{ matrix.target.vcvars }}
-
- - name: Add LLVM to path
- run: echo "C:/Program Files/LLVM/bin" >> $env:GITHUB_PATH
-
- - name: Download Ninja
- run: >
- Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip -OutFile ninja-win.zip &&
- Expand-Archive ninja-win.zip -DestinationPath .
-
- - name: Setup NuGet Credentials
- run: >
- & (C:/vcpkg/vcpkg --vcpkg-root "${{ env.VCPKG_ROOT }}" fetch nuget | tail -n 2)
- sources add
- -source "https://nuget.pkg.github.com/86Box/index.json"
- -storepasswordincleartext
- -name "GitHub"
- -username "86Box"
- -password "${{ secrets.GITHUB_TOKEN }}"
-
- - name: Fix MSVC atomic headers
- run: dir "C:/Program Files/Microsoft Visual Studio/2022/*/VC/Tools/MSVC/*/include" -include stdatomic.h -recurse | del
-
- - name: Checkout repository
- uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
-
- - name: Install sonar-scanner and build-wrapper
- uses: SonarSource/sonarcloud-github-c-cpp@v2
-
- - name: Configure CMake
- run: >
- cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
- --toolchain C:/vcpkg/scripts/buildsystems/vcpkg.cmake
- -D NEW_DYNAREC=${{ matrix.dynarec.new }} -D QT=${{ matrix.ui.qt }}
- -D CMAKE_INSTALL_PREFIX=./build/artifacts
- -D VCPKG_CHAINLOAD_TOOLCHAIN_FILE=${{ github.workspace }}/${{ matrix.target.toolchain }}
- -D VCPKG_TARGET_TRIPLET=${{ matrix.target.triplet }}
- -D VCPKG_HOST_TRIPLET=x64-windows
- -D VCPKG_USE_HOST_TOOLS=ON
-
- - name: Fix Qt
- if: matrix.ui.qt == 'on'
- run: |
- $qtTargetsPath = "${{ github.workspace }}/build/vcpkg_installed/${{ matrix.target.triplet }}/share/Qt6/Qt6Targets.cmake"
- (Get-Content $qtTargetsPath) -replace "^.*-Zc:__cplusplus;-permissive-.*$","#$&" | Set-Content $qtTargetsPath
-
- - name: Reconfigure CMake
- if: matrix.ui.qt == 'on'
- run: |
- cmake clean build
-
- - name: Build
- run: |
- .sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
-
- - name: Run sonar-scanner
- if: 0
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- run: |
- .sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
-
- - name: Generate package
- run: |
- cmake --install build
-
- - name: Upload artifact
- uses: actions/upload-artifact@v3
- with:
- name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-LLVM-${{ matrix.target.name }}-gha${{ github.run_number }}'
- path: build/artifacts/**
diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml
index 46fc25b67f..d415c78215 100644
--- a/.github/workflows/cmake_windows_msys2.yml
+++ b/.github/workflows/cmake_windows_msys2.yml
@@ -8,7 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- - .github/workflows/cmake.yml
+ - .github/workflows/cmake_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -19,7 +19,7 @@ on:
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- - .github/workflows/cmake.yml
+ - .github/workflows/cmake_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -63,14 +63,13 @@ jobs:
slug: -Qt
packages: >-
qt5-static:p
-# qt5-base:p
-# qt5-tools:p
+ vulkan-headers:p
environment:
# - msystem: MSYS
# toolchain: ./cmake/flags-gcc-x86_64.cmake
- - msystem: MINGW32
- prefix: mingw-w64-i686
- toolchain: ./cmake/flags-gcc-i686.cmake
+# - msystem: MINGW32
+# prefix: mingw-w64-i686
+# toolchain: ./cmake/flags-gcc-i686.cmake
- msystem: MINGW64
prefix: mingw-w64-x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
@@ -80,9 +79,9 @@ jobs:
# - msystem: CLANG64
# prefix: mingw-w64-clang-x86_64
# toolchain: ./cmake/llvm-win32-x86_64.cmake
- - msystem: UCRT64
- prefix: mingw-w64-ucrt-x86_64
- toolchain: ./cmake/flags-gcc-x86_64.cmake
+# - msystem: UCRT64
+# prefix: mingw-w64-ucrt-x86_64
+# toolchain: ./cmake/flags-gcc-x86_64.cmake
steps:
- name: Prepare MSYS2 environment
@@ -104,7 +103,6 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
- libvncserver:p
${{ matrix.ui.packages }}
- name: Checkout repository
@@ -113,7 +111,7 @@ jobs:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install sonar-scanner and build-wrapper
- uses: SonarSource/sonarcloud-github-c-cpp@v2
+ uses: SonarSource/sonarcloud-github-c-cpp@5c3c39143e381909307f6903f13774b275ed956d
- name: Configure CMake
run: >-
@@ -140,7 +138,7 @@ jobs:
run: cmake --install build
- name: Upload artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}'
path: build/artifacts/**
diff --git a/.github/workflows/codeql_linux.yml b/.github/workflows/codeql_linux.yml
index a97951abf3..73ccfb2146 100644
--- a/.github/workflows/codeql_linux.yml
+++ b/.github/workflows/codeql_linux.yml
@@ -8,7 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- - .github/workflows/codeql.yml
+ - .github/workflows/codeql_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -19,7 +19,7 @@ on:
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- - .github/workflows/codeql.yml
+ - .github/workflows/codeql_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -83,14 +83,13 @@ jobs:
libopenal-dev
libslirp-dev
libfluidsynth-dev
- libvncserver-dev
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
@@ -107,6 +106,6 @@ jobs:
run: cmake --build build
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml
index 724bdc6f68..adf34cb54b 100644
--- a/.github/workflows/codeql_macos.yml
+++ b/.github/workflows/codeql_macos.yml
@@ -8,7 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- - .github/workflows/codeql.yml
+ - .github/workflows/codeql_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -19,7 +19,7 @@ on:
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- - .github/workflows/codeql.yml
+ - .github/workflows/codeql_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -70,20 +70,17 @@ jobs:
run: >-
brew install
ninja
- freetype
sdl2
- libpng
rtmidi
openal-soft
fluidsynth
- libvncserver
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
@@ -103,6 +100,6 @@ jobs:
run: cmake --build build
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml
index 5b0c2485f3..2b468f9960 100644
--- a/.github/workflows/codeql_windows_msys2.yml
+++ b/.github/workflows/codeql_windows_msys2.yml
@@ -8,7 +8,7 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- - .github/workflows/codeql.yml
+ - .github/workflows/codeql_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -19,7 +19,7 @@ on:
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- - .github/workflows/codeql.yml
+ - .github/workflows/codeql_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -61,9 +61,6 @@ jobs:
new: on
slug: -NDR
ui:
- - name: Win32 GUI
- qt: off
- static: on
- name: Qt GUI
qt: on
static: off
@@ -71,6 +68,7 @@ jobs:
packages: >-
qt5-base:p
qt5-tools:p
+ vulkan-headers:p
environment:
# - msystem: MSYS
# toolchain: ./cmake/flags-gcc-x86_64.cmake
@@ -110,14 +108,13 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
- libvncserver:p
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
@@ -136,6 +133,6 @@ jobs:
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
diff --git a/.gitignore b/.gitignore
index 48a5950b91..5a43dffdb6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,6 @@ CMakeLists.txt.user
# MacOS Finder stuff
.DS_Store
+
+# clangd
+.cache
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a6b50baf32..fa1d02a151 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,7 +35,7 @@ if(MUNT_EXTERNAL)
endif()
project(86Box
- VERSION 4.1
+ VERSION 4.2
DESCRIPTION "Emulator of x86-based systems"
HOMEPAGE_URL "https://86box.net"
LANGUAGES C CXX)
@@ -131,14 +131,19 @@ option(RTMIDI "RtMidi"
option(FLUIDSYNTH "FluidSynth" ON)
option(MUNT "MUNT" ON)
option(VNC "VNC renderer" OFF)
-option(DINPUT "DirectInput" OFF)
option(CPPTHREADS "C++11 threads" ON)
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF)
option(GDBSTUB "Enable GDB stub server for debugging" OFF)
option(DEV_BRANCH "Development branch" OFF)
-option(QT "Qt GUI" ON)
option(DISCORD "Discord Rich Presence support" ON)
+option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF)
+
+if(WIN32)
+ set(QT ON)
+else()
+ option(QT "Qt GUI" ON)
+endif()
# Development branch features
#
@@ -147,7 +152,6 @@ option(DISCORD "Discord Rich Presence support"
cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF)
cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF)
cmake_dependent_option(CYRIX_6X86 "Cyrix 6x86" ON "DEV_BRANCH" OFF)
-cmake_dependent_option(DESKPRO386 "Compaq Deskpro 386" ON "DEV_BRANCH" OFF)
cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF)
cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF)
cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF)
@@ -155,9 +159,8 @@ cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT"
cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
-cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF)
+cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF)
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
-cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF)
cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF)
# Ditto but for Qt
diff --git a/README.md b/README.md
index 370bc940ee..b4b4142be5 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,9 @@ Performance may vary depending on both host and guest configuration. Most emulat
It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines.
* [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only)
-* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by Dungeonseeker (Linux focused, should work on Windows though untested)
+* [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia)
+* [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python)
+* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested)
* [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only)
It is also possible to use 86Box on its own with the `--vmpath`/`-P` command line option.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000..fe83948838
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,18 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+| --------- | ------------------ |
+| >= master | :white_check_mark: |
+| < master | :x: |
+
+Each version is supported in the form of patch releases until the next version is merged into master.
+
+## Reporting a Vulnerability
+
+To report a vulnerability, either open an issue here on GitHub or join our Discord server. If it is
+accepted, that means we have begun working on it and it will be fixed if it is at all possible. If it
+is declined, then that means we have either determined it to not actually be a vulnerability or we
+have determined it is not feasible to fix it. On GitHub, we are going to notify you when a decision
+taken, and if accepted, when it is fixed. On Discord, you get live updates.
diff --git a/bumpversion.sh b/bumpversion.sh
index 4681e72bec..6e2536cbe7 100644
--- a/bumpversion.sh
+++ b/bumpversion.sh
@@ -26,12 +26,6 @@ then
fi
shift
-# Extract version components.
-newversion_maj=$(echo "$newversion" | cut -d. -f1)
-newversion_min=$(echo "$newversion" | cut -d. -f2)
-newversion_patch=$(echo "$newversion" | cut -d. -f3)
-[ -z "$newversion_patch" ] && newversion_patch=0
-
if [ -z "${romversion}" ]; then
# Get the latest ROM release from the GitHub API.
romversion=$(curl --silent "https://api.github.com/repos/86Box/roms/releases/latest" |
@@ -62,12 +56,6 @@ patch_file() {
}
patch_file CMakeLists.txt VERSION 's/^(\s*VERSION ).+/\1'"$newversion"'/'
patch_file vcpkg.json version-string 's/(^\s*"version-string"\s*:\s*")[^"]+/\1'"$newversion"'/'
-patch_file src/include_make/*/version.h EMU_VERSION 's/(#\s*define\s+EMU_VERSION\s+")[^"]+/\1'"$newversion"'/'
-patch_file src/include_make/*/version.h EMU_VERSION_MAJ 's/(#\s*define\s+EMU_VERSION_MAJ\s+)[0-9]+/\1'"$newversion_maj"'/'
-patch_file src/include_make/*/version.h EMU_VERSION_MIN 's/(#\s*define\s+EMU_VERSION_MIN\s+)[0-9]+/\1'"$newversion_min"'/'
-patch_file src/include_make/*/version.h EMU_VERSION_PATCH 's/(#\s*define\s+EMU_VERSION_PATCH\s+)[0-9]+/\1'"$newversion_patch"'/'
-patch_file src/include_make/*/version.h COPYRIGHT_YEAR 's/(#\s*define\s+COPYRIGHT_YEAR\s+)[0-9]+/\1'"$(date +%Y)"'/'
-patch_file src/include_make/*/version.h EMU_DOCS_URL 's/(#\s*define\s+EMU_DOCS_URL\s+"https:\/\/[^\/]+\/en\/v)[^\/]+/\1'"$newversion_maj.$newversion_min"'/'
patch_file src/unix/assets/*.spec Version 's/(Version:\s+)[0-9].+/\1'"$newversion"'/'
patch_file src/unix/assets/*.spec '%global romver' 's/(^%global\ romver\s+)[0-9]{8}/\1'"$romversion"'/'
patch_file src/unix/assets/*.spec 'changelog version' 's/(^[*]\s.*>\s+)[0-9].+/\1'"$newversion"-1'/'
diff --git a/debian/changelog b/debian/changelog
index 29ec6d3afa..fe8aa68213 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,5 @@
-86box (4.1) UNRELEASED; urgency=medium
+86box (4.2) UNRELEASED; urgency=medium
* Bump release.
- -- Jasmine Iwanek Mon, 16 Oct 2023 20:24:46 +0200
+ -- Jasmine Iwanek Sat, 23 Mar 2024 17:19:08 +0100
diff --git a/src/86box.c b/src/86box.c
index 8218c208cf..61b81bbf3e 100644
--- a/src/86box.c
+++ b/src/86box.c
@@ -66,6 +66,7 @@
#include <86box/bugger.h>
#include <86box/postcard.h>
#include <86box/unittester.h>
+#include <86box/novell_cardkey.h>
#include <86box/isamem.h>
#include <86box/isartc.h>
#include <86box/lpt.h>
@@ -173,6 +174,7 @@ char video_shader[512] = { '\0' }; /* (C) video *
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0 }; /* (C) activation and kind of
pass-through for serial ports */
int bugger_enabled = 0; /* (C) enable ISAbugger */
+int novell_keycard_enabled = 0; /* (C) enable Novell NetWare 2.x key card emulation. */
int postcard_enabled = 0; /* (C) enable POST card */
int unittester_enabled = 0; /* (C) enable unit tester device */
int isamem_type[ISAMEM_MAX] = { 0, 0, 0, 0 }; /* (C) enable ISA mem cards */
@@ -181,6 +183,7 @@ int gfxcard[2] = { 0, 0 }; /* (C) graphic
int show_second_monitors = 1; /* (C) show non-primary monitors */
int sound_is_float = 1; /* (C) sound uses FP values */
int voodoo_enabled = 0; /* (C) video option */
+int lba_enhancer_enabled = 0; /* (C) enable Vision Systems LBA Enhancer */
int ibm8514_standalone_enabled = 0; /* (C) video option */
int xga_standalone_enabled = 0; /* (C) video option */
uint32_t mem_size = 0; /* (C) memory size (Installed on
@@ -203,6 +206,12 @@ int video_fullscreen_scale_maximized = 0; /* (C) Whether
also apply when maximized. */
int do_auto_pause = 0; /* (C) Auto-pause the emulator on focus
loss */
+char uuid[MAX_UUID_LEN] = { '\0' }; /* (C) UUID or machine identifier */
+
+int other_ide_present = 0; /* IDE controllers from non-IDE cards are
+ present */
+int other_scsi_present = 0; /* SCSI controllers from non-SCSI cards are
+ present */
/* Statistics. */
extern int mmuflush;
@@ -951,12 +960,12 @@ pc_init_modules(void)
/* Load the ROMs for the selected machine. */
if (!machine_available(machine)) {
- swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2063), machine_getname());
+ swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_MACHINE), machine_getname());
c = 0;
machine = -1;
while (machine_get_internal_name_ex(c) != NULL) {
if (machine_available(c)) {
- ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp);
+ ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), temp);
machine = c;
config_save();
break;
@@ -973,12 +982,12 @@ pc_init_modules(void)
if (!video_card_available(gfxcard[0])) {
memset(tempc, 0, sizeof(tempc));
device_get_name(video_card_getdevice(gfxcard[0]), 0, tempc);
- swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2064), tempc);
+ swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_VIDEO), tempc);
c = 0;
while (video_get_internal_name(c) != NULL) {
gfxcard[0] = -1;
if (video_card_available(c)) {
- ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp);
+ ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), temp);
gfxcard[0] = c;
config_save();
break;
@@ -994,8 +1003,8 @@ pc_init_modules(void)
if (!video_card_available(gfxcard[1])) {
char tempc[512] = { 0 };
device_get_name(video_card_getdevice(gfxcard[1]), 0, tempc);
- swprintf(temp, sizeof_w(temp), plat_get_string(IDS_2163), tempc);
- ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp);
+ swprintf(temp, sizeof_w(temp), plat_get_string(STRING_HW_NOT_AVAILABLE_VIDEO2), tempc);
+ ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), temp);
gfxcard[1] = 0;
}
@@ -1076,18 +1085,22 @@ pc_reset_hard_close(void)
/* Close all the memory mappings. */
mem_close();
+ suppress_overscan = 0;
+
/* Turn off timer processing to avoid potential segmentation faults. */
timer_close();
- suppress_overscan = 0;
+ lpt_devices_close();
+
+#ifdef UNCOMMENT_LATER
+ lpt_close();
+#endif
nvr_save();
nvr_close();
mouse_close();
- lpt_devices_close();
-
device_close_all();
scsi_device_close_all();
@@ -1128,6 +1141,9 @@ pc_reset_hard_init(void)
* modules that are.
*/
+ /* Reset the IDE and SCSI presences */
+ other_ide_present = other_scsi_present = 0;
+
/* Mark ACPI as unavailable */
acpi_enabled = 0;
@@ -1167,13 +1183,14 @@ pc_reset_hard_init(void)
/* note: PLIP LPT side has to be initialized before the network side */
lpt_devices_init();
- /* Reset and reconfigure the Network Card layer. */
- network_reset();
-
/* Reset and reconfigure the serial ports. */
+ /* note: SLIP COM side has to be initialized before the network side */
serial_standalone_init();
serial_passthrough_init();
+ /* Reset and reconfigure the Network Card layer. */
+ network_reset();
+
/*
* Reset the mouse, this will attach it to any port needed.
*/
@@ -1227,6 +1244,12 @@ pc_reset_hard_init(void)
if (unittester_enabled)
device_add(&unittester_device);
+ if (lba_enhancer_enabled)
+ device_add(&lba_enhancer_device);
+
+ if (novell_keycard_enabled)
+ device_add(&novell_keycard_device);
+
if (IS_ARCH(machine, MACHINE_BUS_PCI)) {
pci_register_cards();
device_reset_all(DEVICE_PCI);
@@ -1279,17 +1302,17 @@ update_mouse_msg(void)
mbstowcs(wcpu, cpu_s->name, strlen(cpu_s->name) + 1);
#ifdef _WIN32
swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls",
- plat_get_string(IDS_2077));
+ plat_get_string(STRING_MOUSE_CAPTURE));
swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%%i%%%% - %ls",
- (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079));
+ (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB));
wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2]));
#else
swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls",
EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu,
- plat_get_string(IDS_2077));
+ plat_get_string(STRING_MOUSE_CAPTURE));
swprintf(mouse_msg[1], sizeof_w(mouse_msg[1]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls - %ls",
EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu,
- (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079));
+ (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB));
swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls",
EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu);
#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ec32d7548a..93a6f4d4c5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,7 +21,7 @@ endif()
add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
dma.c ddma.c nmi.c pic.c pit.c pit_fast.c port_6x.c port_92.c ppi.c pci.c
mca.c usb.c fifo.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c
- machine_status.c ini.c)
+ machine_status.c ini.c cJSON.c)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
@@ -57,12 +57,16 @@ if(DISCORD)
target_sources(86Box PRIVATE discord.c)
endif()
+if(DEBUGREGS486)
+ add_compile_definitions(USE_DEBUG_REGS_486)
+endif()
+
if(VNC)
find_package(LibVNCServer)
if(LibVNCServer_FOUND)
add_compile_definitions(USE_VNC)
add_library(vnc OBJECT vnc.c vnc_keymap.c)
- target_link_libraries(86Box vnc LibVNCServer::vncserver)
+ target_link_libraries(86Box vnc LibVNCServer::vncserver)
if(WIN32)
target_link_libraries(86Box ws2_32)
endif()
@@ -226,8 +230,6 @@ endif()
if (QT)
add_subdirectory(qt)
-elseif(WIN32)
- add_subdirectory(win)
else()
add_compile_definitions(USE_SDL_UI)
add_subdirectory(unix)
diff --git a/src/Makefile.local b/src/Makefile.local
deleted file mode 100644
index fdb2dcab33..0000000000
--- a/src/Makefile.local
+++ /dev/null
@@ -1,200 +0,0 @@
-#
-# 86Box A hypervisor and IBM PC system emulator that specializes in
-# running old operating systems and software designed for IBM
-# PC systems and compatibles from 1981 through fairly recent
-# system designs based on the PCI bus.
-#
-# This file is part of the 86Box distribution.
-#
-# Prefix for localizing the general Makefile.mingw for local
-# settings, so we can avoid changing the main one for all of
-# our local setups.
-#
-# Authors: Fred N. van Kempen,
-#
-
-#########################################################################
-# Anything here will override defaults in Makefile.MinGW. #
-#########################################################################
-
-
-# Name of the executable.
-#PROG := 86box.exe
-
-
-# Various compile-time options.
-# -DROM_TRACE=0xc800 traces ROM access from segment C800
-# -DIO_TRACE=0x66 traces I/O on port 0x66
-# -DIO_CATCH enables I/O range catch logs
-STUFF :=
-
-# Add feature selections here.
-# -DANSI_CFG forces the config file to ANSI encoding.
-# Root logging:
-# -DENABLE_ACPI_LOG=N sets logging level at N.
-# -DENABLE_APM_LOG=N sets logging level at N.
-# -DENABLE_BUGGER_LOG=N sets logging level at N.
-# -DENABLE_CONFIG_LOG=N sets logging level at N.
-# -DENABLE_DDMA_LOG=N sets logging level at N.
-# -DENABLE_DEVICE_LOG=N sets logging level at N.
-# -DENABLE_DMA_LOG=N sets logging level at N.
-# -DENABLE_IO_LOG=N sets logging level at N.
-# -DENABLE_IOAPIC_LOG=N sets logging level at N.
-# -DENABLE_ISAMEM_LOG=N sets logging level at N.
-# -DENABLE_ISARTC_LOG=N sets logging level at N.
-# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N.
-# -DENABLE_KEYBOARD_XT_LOG=N sets logging level at N.
-# -DENABLE_LM75_LOG=N sets logging level at N.
-# -DENABLE_LM78_LOG=N sets logging level at N.
-# -DENABLE_MEM_LOG=N sets logging level at N.
-# -DENABLE_MOUSE_LOG=N sets logging level at N.
-# -DENABLE_MOUSE_BUS_LOG=N sets logging level at N.
-# -DENABLE_MOUSE_PS2_LOG=N sets logging level at N.
-# -DENABLE_MOUSE_SERIAL_LOG=N sets logging level at N.
-# -DENABLE_NVR_LOG=N sets logging level at N.
-# -DENABLE_PC_LOG=N sets logging level at N.
-# -DENABLE_PCI_LOG=N sets logging level at N.
-# -DENABLE_PIC_LOG=N sets logging level at N.
-# -DENABLE_PIT_LOG=N sets logging level at N.
-# -DENABLE_POSTCARD_LOG=N sets logging level at N.
-# -DENABLE_ROM_LOG=N sets logging level at N.
-# -DENABLE_SERIAL_LOG=N sets logging level at N.
-# -DENABLE_SMBUS_LOG=N sets logging level at N.
-# -DENABLE_SMBUS_PIIX4_LOG=N sets logging level at N.
-# -DENABLE_SPD_LOG=N sets logging level at N.
-# -DENABLE_USB_LOG=N sets logging level at N.
-# -DENABLE_VNC_LOG=N sets logging level at N.
-# -DENABLE_VNC_KEYMAP_LOG=N sets logging level at N.
-# cdrom/ logging:
-# -DENABLE_CDROM_LOG=N sets logging level at N.
-# -DENABLE_CDROM_IMAGE_LOG=N sets logging level at N.
-# -DENABLE_CDROM_IMAGE_BACKEND_LOG=N sets logging level at N.
-# chipset/ logging:
-# -DENABLE_I420EX_LOG=N sets logging level at N.
-# -DENABLE_NEAT_LOG=N sets logging level at N.
-# -DENABLE_OPTI495_LOG=N sets logging level at N.
-# -DENABLE_OPTI895_LOG=N sets logging level at N.
-# -DENABLE_PIIX_LOG=N sets logging level at N.
-# -DENABLE_SIO_LOG=N sets logging level at N.
-# -DENABLE_SIS_85C496_LOG=N sets logging level at N.
-# codegen/, codegen_new/, cpu/ logging:
-# -DENABLE_X86SEG_LOG=N sets logging level at N.
-# cpu/ logging:
-# -DENABLE_386_LOG=N sets logging level at N.
-# -DENABLE_386_COMMON_LOG=N sets logging level at N.
-# -DENABLE_386_DYNAREC_LOG=N sets logging level at N.
-# -DENABLE_808X_LOG=N sets logging level at N.
-# -DENABLE_CPU_LOG=N sets logging level at N.
-# -DENABLE_FPU_LOG=N sets logging level at N.
-# disk/ logging:
-# -DENABLE_ESDI_AT_LOG=N sets logging level at N.
-# -DENABLE_ESDI_MCA_LOG=N sets logging level at N.
-# -DENABLE_HDC_LOG=N sets logging level at N.
-# -DENABLE_HDD_IMAGE_LOG=N sets logging level at N.
-# -DENABLE_IDE_LOG=N sets logging level at N.
-# -DENABLE_MO_LOG=N sets logging level at N.
-# -DENABLE_SFF_LOG=N sets logging level at N.
-# -DENABLE_ST506_AT_LOG=N sets logging level at N.
-# -DENABLE_ST506_XT_LOG=N sets logging level at N.
-# -DENABLE_XTA_LOG=N sets logging level at N.
-# -DENABLE_ZIP_LOG=N sets logging level at N.
-# floppy/ logging:
-# -DENABLE_D86F_LOG=N sets logging level at N.
-# -DENABLE_FDC_LOG=N sets logging level at N.
-# -DENABLE_FDD_LOG=N sets logging level at N.
-# -DENABLE_FDI_LOG=N sets logging level at N.
-# -DENABLE_FDI2RAW_LOG=N sets logging level at N.
-# -DENABLE_IMD_LOG=N sets logging level at N.
-# -DENABLE_IMG_LOG=N sets logging level at N.
-# -DENABLE_JSON_LOG=N sets logging level at N.
-# -DENABLE_MFM_LOG=N sets logging level at N.
-# -DENABLE_TD0_LOG=N sets logging level at N.
-# machine/ logging:
-# -DENABLE_AMSTRAD_LOG=N sets logging level at N.
-# -DENABLE_EUROPC_LOG=N sets logging level at N.
-# -DENABLE_M24VID_LOG=N sets logging level at N.
-# -DENABLE_MACHINE_LOG=N sets logging level at N.
-# -DENABLE_PS1_HDC_LOG=N sets logging level at N.
-# -DENABLE_PS2_MCA_LOG=N sets logging level at N.
-# -DENABLE_TANDY_LOG=N sets logging level at N.
-# -DENABLE_T1000_LOG=N sets logging level at N.
-# -DENABLE_T3100E_LOG=N sets logging level at N.
-# network/ logging:
-# -DENABLE_3COM503_LOG=N sets logging level at N.
-# -DENABLE_DP8390_LOG=N sets logging level at N.
-# -DENABLE_NETWORK_LOG=N sets logging level at N.
-# -DENABLE_NE2K_LOG=N sets logging level at N.
-# -DENABLE_PCAP_LOG=N sets logging level at N.
-# -DENABLE_PCNET_LOG=N sets logging level at N.
-# -DENABLE_SLIRP_LOG=N sets logging level at N.
-# -DENABLE_WD_LOG=N sets logging level at N.
-# printer/ logging:
-# -DENABLE_ESCP_LOG=N sets logging level at N.
-# scsi/ logging:
-# -DENABLE_AHA154X_LOG=N sets logging level at N.
-# -DENABLE_BUSLOGIC_LOG=N sets logging level at N.
-# -DENABLE_NCR5380_LOG=N sets logging level at N.
-# -DENABLE_NCR53C8XX_LOG=N sets logging level at N.
-# -DENABLE_SCSI_CDROM_LOG=N sets logging level at N.
-# -DENABLE_SCSI_DISK_LOG=N sets logging level at N.
-# -DENABLE_SPOCK_LOG=N sets logging level at N.
-# -DENABLE_X54X_LOG=N sets logging level at N.
-# sound/ logging:
-# -DENABLE_ADLIB_LOG=N sets logging level at N.
-# -DENABLE_AUDIOPCI_LOG=N sets logging level at N.
-# -DENABLE_EMU8K_LOG=N sets logging level at N.
-# -DENABLE_MPU401_LOG=N sets logging level at N.
-# -DENABLE_PAS16_LOG=N sets logging level at N.
-# -DENABLE_SB_LOG=N sets logging level at N.
-# -DENABLE_SB_DSP_LOG=N sets logging level at N.
-# -DENABLE_SOUND_LOG=N sets logging level at N.
-# video/ logging:
-# -DENABLE_ATI28800_LOG=N sets logging level at N.
-# -DENABLE_MACH64_LOG=N sets logging level at N.
-# -DENABLE_COMPAQ_CGA_LOG=N sets logging level at N.
-# -DENABLE_ET4000W32_LOG=N sets logging level at N.
-# -DENABLE_HT216_LOG=N sets logging level at N.
-# -DENABLE_ICD2061_LOG=N sets logging level at N.
-# -DENABLE_IM1024_LOG=N sets logging level at N.
-# -DENABLE_PGC_LOG=N sets logging level at N.
-# -DENABLE_S3_VIRGE_LOG=N sets logging level at N.
-# -DENABLE_VID_TABLE_LOG=N sets logging level at N.
-# -DENABLE_VIDEO_LOG=N sets logging level at N.
-# -DENABLE_VOODOO_LOG=N sets logging level at N.
-# win/ logging:
-# -DENABLE_WIN_LOG=N sets logging level at N.
-# -DENABLE_DISCORD_LOG=N sets logging level at N.
-# -DENABLE_DYNLD_LOG=N sets logging level at N.
-# -DENABLE_JOYSTICK_LOG=N sets logging level at N.
-# -DENABLE_SDL_LOG=N sets logging level at N.
-# -DENABLE_SETTINGS_LOG=N sets logging level at N.
-EXTRAS :=
-
-
-AUTODEP := n
-DEBUG := n
-OPTIM := n
-X64 := n
-RELEASE := n
-USB := n
-VNC := n
-RDP := n
-DEV_BUILD := n
-DEV_BRANCH := n
-CIRRUS := n
-NE1000 := n
-NV_RIVA := n
-OPENAL := y
-FLUIDSYNTH := y
-MUNT := y
-PAS16 := n
-DYNAREC := y
-
-
-#########################################################################
-# Include the master Makefile.MinGW for the rest. #
-#########################################################################
-include win/Makefile.mingw
-
-
-# End of Makefile.local.
diff --git a/src/acpi.c b/src/acpi.c
index ddd2ffbe75..339ea7dcfe 100644
--- a/src/acpi.c
+++ b/src/acpi.c
@@ -39,6 +39,10 @@
#include <86box/machine.h>
#include <86box/i2c.h>
#include <86box/video.h>
+#include <86box/smbus.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/sis_55xx.h>
int acpi_rtc_status = 0;
atomic_int acpi_pwrbut_pressed = 0;
@@ -46,7 +50,9 @@ int acpi_enabled = 0;
static double cpu_to_acpi;
-static int acpi_power_on = 0;
+static int acpi_power_on = 0;
+static uint64_t acpi_last_clock = 0ULL;
+static int acpi_count = 0;
#ifdef ENABLE_ACPI_LOG
int acpi_do_log = ENABLE_ACPI_LOG;
@@ -82,65 +88,152 @@ acpi_timer_get(acpi_t *dev)
return clock & 0xffffff;
}
+static uint8_t
+acpi_gp_timer_get(acpi_t *dev)
+{
+ uint64_t clock = acpi_clock_get();
+ clock -= acpi_last_clock;
+ if (clock >= acpi_count)
+ clock = 0x00;
+ else
+ clock &= 0xff;
+ return clock;
+}
+
static double
acpi_get_overflow_period(acpi_t *dev)
{
uint64_t timer = acpi_clock_get();
uint64_t overflow_time;
- if (dev->regs.timer32) {
+ if (dev->regs.timer32)
overflow_time = (timer + 0x80000000LL) & ~0x7fffffffLL;
- } else {
+ else
overflow_time = (timer + 0x800000LL) & ~0x7fffffLL;
- }
uint64_t time_to_overflow = overflow_time - timer;
return ((double) time_to_overflow / (double) ACPI_TIMER_FREQ) * 1000000.0;
}
+static void
+acpi_timer_update(acpi_t *dev, bool enable)
+{
+ if (enable)
+ timer_on_auto(&dev->timer, acpi_get_overflow_period(dev));
+ else
+ timer_stop(&dev->timer);
+}
+
static void
acpi_timer_overflow(void *priv)
{
acpi_t *dev = (acpi_t *) priv;
dev->regs.pmsts |= TMROF_STS;
acpi_update_irq(dev);
+ acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS));
}
static void
-acpi_timer_update(acpi_t *dev, bool enable)
+acpi_gp_timer_update(acpi_t *dev, bool enable, int count)
{
if (enable) {
- timer_on_auto(&dev->timer, acpi_get_overflow_period(dev));
- } else {
+ acpi_last_clock = acpi_clock_get();
+ acpi_count = count;
+ timer_on_auto(&dev->gp_timer, (1000000.0 / (double) ACPI_TIMER_FREQ) * ((double) count));
+ } else
timer_stop(&dev->timer);
+}
+
+void
+acpi_sis5595_smi_raise(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+ if (dev->regs.leg_en & 0x20) {
+ dev->regs.leg_sts |= 0x20;
+ smi_raise();
+ }
+}
+
+static void
+acpi_gp_timer(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+ if (dev->vendor == VEN_SIS_5595_1997) {
+ dev->regs.gpe_sts |= 0x20000000;
+ dev->regs.leg_sts |= 0x20;
+ acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x20000000), acpi_count);
+ acpi_sis5595_smi_raise(dev);
+ } else if (dev->vendor == VEN_SIS_5595) {
+ dev->regs.gpe_sts |= 0x00000400;
+ dev->regs.leg_sts |= 0x20;
+ acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x00000400), acpi_count);
+ acpi_sis5595_smi_raise(dev);
+ } else {
+ dev->regs.reg_14 |= 0x2000;
+ acpi_gp_timer_update(dev, (dev->regs.reg_16 & 0x2000), acpi_count);
+ smi_raise();
+ }
+}
+
+static void
+acpi_per_timer(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+ if (dev->vendor >= VEN_SIS_5595_1997) {
+ dev->regs.leg_sts |= 0x04;
+ acpi_sis5595_smi_raise(dev);
+ } else {
+ dev->regs.reg_25 |= 0x04;
+ smi_raise();
}
+ timer_on_auto(&dev->per_timer, 16000000.0);
}
void
acpi_update_irq(acpi_t *dev)
{
int sci_level = (dev->regs.pmsts & dev->regs.pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN);
- if (dev->vendor == VEN_SMC)
- sci_level |= (dev->regs.pmsts & BM_STS);
+ sis_55xx_common_t *sis = (sis_55xx_common_t *) dev->priv;
+
+ switch (dev->vendor) {
+ case VEN_SMC:
+ sci_level |= (dev->regs.pmsts & BM_STS);
+ break;
+ case VEN_SIS_5595_1997:
+ case VEN_SIS_5595:
+ if ((sis != NULL) && (sis->pmu_regs != NULL)) {
+ sci_level |= (sis->pmu_regs[0x80] | sis->pmu_regs[0x81] |
+ sis->pmu_regs[0x82] | sis->pmu_regs[0x83]);
+ }
+ break;
+ }
- if ((dev->regs.pmcntrl & 0x01) && sci_level) {
- if (dev->irq_mode == 1)
+ if ((dev->regs.pmcntrl & 0x01) && sci_level) switch (dev->irq_mode) {
+ default:
+ picintlevel(1 << dev->irq_line, &dev->irq_state);
+ break;
+ case 1:
pci_set_irq(dev->slot, dev->irq_pin, &dev->irq_state);
- else if (dev->irq_mode == 2)
+ break;
+ case 2:
pci_set_mirq(5, dev->mirq_is_level, &dev->irq_state);
- else
- picintlevel(1 << dev->irq_line, &dev->irq_state);
- } else {
- if (dev->irq_mode == 1)
+ break;
+ case -1:
+ break;
+ } else switch (dev->irq_mode) {
+ default:
+ picintclevel(1 << dev->irq_line, &dev->irq_state);
+ break;
+ case 1:
pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state);
- else if (dev->irq_mode == 2)
+ break;
+ case 2:
pci_clear_mirq(5, dev->mirq_is_level, &dev->irq_state);
- else
- picintclevel(1 << dev->irq_line, &dev->irq_state);
+ break;
+ case -1:
+ break;
}
-
- acpi_timer_update(dev, (dev->regs.pmen & TMROF_EN) && !(dev->regs.pmsts & TMROF_STS));
}
void
@@ -652,6 +745,230 @@ acpi_aux_reg_read_smc(UNUSED(int size), uint16_t addr, void *priv)
return ret;
}
+static uint32_t
+acpi_reg_read_sis_5582(int size, uint16_t addr, void *priv)
+{
+ const acpi_t *dev = (acpi_t *) priv;
+ uint32_t ret = 0x00000000;
+ int shift16;
+ int shift32;
+
+ addr &= 0x3f;
+ shift16 = (addr & 1) << 3;
+ shift32 = (addr & 3) << 3;
+
+ switch (addr) {
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ ret = (dev->regs.reg_0c >> shift32) & 0xff;
+ break;
+ case 0x10:
+ ret = dev->regs.enter_c2_ps;
+ break;
+ case 0x11:
+ ret = dev->regs.enter_c3_ps;
+ break;
+ case 0x12:
+ ret = dev->regs.reg_12;
+ break;
+ case 0x13:
+ ret = acpi_gp_timer_get((acpi_t *) dev) & 0xff;
+#ifdef USE_DYNAREC
+ if (cpu_use_dynarec)
+ update_tsc();
+#endif
+ break;
+ case 0x14:
+ case 0x15:
+ ret = (dev->regs.reg_14 >> shift16) & 0xff;
+ break;
+ case 0x16:
+ case 0x17:
+ ret = (dev->regs.reg_16 >> shift16) & 0xff;
+ break;
+ case 0x18:
+ case 0x19:
+ ret = (dev->regs.reg_18 >> shift16) & 0xff;
+ break;
+ case 0x1a:
+ case 0x1b:
+ ret = (dev->regs.reg_18 >> shift16) & 0xff;
+ break;
+ case 0x1c:
+ case 0x1d:
+ ret = (dev->regs.reg_1c >> shift16) & 0xff;
+ break;
+ case 0x20:
+ ret = dev->regs.smi_cmd;
+ break;
+ case 0x24:
+ ret = dev->regs.reg_24;
+ break;
+ case 0x25:
+ ret = dev->regs.reg_25;
+ break;
+ case 0x26:
+ ret = dev->regs.reg_26;
+ break;
+ case 0x28:
+ ret = dev->regs.smi_en_val;
+ break;
+ case 0x29:
+ ret = dev->regs.smi_dis_val;
+ break;
+ case 0x2a:
+ ret = dev->regs.mail_box;
+ break;
+ case 0x2b:
+ ret = dev->regs.reg_2b;
+ break;
+ default:
+ ret = acpi_reg_read_common_regs(size, addr, priv);
+ break;
+ }
+
+#ifdef ENABLE_ACPI_LOG
+ // if (size != 1)
+ // acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret);
+#endif
+ return ret;
+}
+
+static uint32_t
+acpi_reg_read_sis_5595(int size, uint16_t addr, void *priv)
+{
+ const acpi_t *dev = (acpi_t *) priv;
+ uint32_t ret = 0x00000000;
+ int shift16;
+ int shift32;
+
+ addr &= 0x3f;
+ shift16 = (addr & 1) << 3;
+ shift32 = (addr & 3) << 3;
+
+ switch (addr) {
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ ret = (dev->regs.reg_0c >> shift32) & 0xff;
+ break;
+ case 0x10:
+ ret = dev->regs.enter_c2_ps;
+ break;
+ case 0x11:
+ ret = dev->regs.enter_c3_ps;
+ break;
+ case 0x12:
+ ret = dev->regs.reg_12;
+ break;
+ case 0x13:
+ ret = dev->regs.reg_13;
+ break;
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ ret = (dev->regs.gpe_sts >> shift32) & 0xff;
+ break;
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ ret = (dev->regs.gpe_en >> shift32) & 0xff;
+ break;
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ ret = (dev->regs.gpe_pin >> shift32) & 0xff;
+ break;
+ case 0x1f:
+ ret = acpi_gp_timer_get((acpi_t *) dev) & 0xff;
+#ifdef USE_DYNAREC
+ if (cpu_use_dynarec)
+ update_tsc();
+#endif
+ break;
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ ret = (dev->regs.gpe_io >> shift32) & 0xff;
+ break;
+ case 0x24:
+ case 0x25:
+ case 0x26:
+ case 0x27:
+ ret = (dev->regs.gpe_pol >> shift32) & 0xff;
+ break;
+ case 0x28:
+ case 0x29:
+ ret = (dev->regs.gpe_mul >> shift16) & 0xff;
+ break;
+ case 0x2a:
+ case 0x2b:
+ ret = (dev->regs.gpe_ctl >> shift16) & 0xff;
+ break;
+ case 0x2c:
+ case 0x2d:
+ ret = (dev->regs.gpe_smi >> shift16) & 0xff;
+ break;
+ case 0x2e:
+ case 0x2f:
+ ret = (dev->regs.gpe_rl >> shift16) & 0xff;
+ break;
+ case 0x30:
+ ret = dev->regs.leg_sts;
+ break;
+ case 0x31:
+ ret = dev->regs.leg_en;
+ break;
+ case 0x32:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ ret = dev->regs.smi_cmd;
+ else
+ ret = 0x00;
+ break;
+ case 0x33:
+ ret = dev->regs.tst_ctl;
+ break;
+ case 0x34:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ ret = dev->regs.smi_en_val;
+ else
+ ret = dev->regs.reg_34;
+ break;
+ case 0x35:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ ret = dev->regs.smi_dis_val;
+ else
+ ret = dev->regs.smi_cmd;
+ break;
+ case 0x36:
+ ret = dev->regs.mail_box;
+ break;
+ case 0x38:
+ if (dev->vendor == VEN_SIS_5595)
+ ret = smbus_sis5595_read_index(dev->smbus);
+ break;
+ case 0x39:
+ if (dev->vendor == VEN_SIS_5595)
+ ret = smbus_sis5595_read_data(dev->smbus);
+ break;
+ default:
+ ret = acpi_reg_read_common_regs(size, addr, priv);
+ break;
+ }
+
+#ifdef ENABLE_ACPI_LOG
+ // if (size != 1)
+ // acpi_log("(%i) ACPI Read (%i) %02X: %02X\n", in_smm, size, addr, ret);
+#endif
+ return ret;
+}
+
static void
acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *priv)
{
@@ -1193,47 +1510,447 @@ acpi_aux_reg_write_smc(UNUSED(int size), uint16_t addr, uint8_t val, void *priv)
}
}
-static uint32_t
-acpi_reg_read_common(int size, uint16_t addr, void *priv)
+void
+acpi_sis5582_pmu_event(void *priv)
{
- const acpi_t *dev = (acpi_t *) priv;
- uint8_t ret = 0xff;
-
- if (dev->vendor == VEN_ALI)
- ret = acpi_reg_read_ali(size, addr, priv);
- else if (dev->vendor == VEN_VIA)
- ret = acpi_reg_read_via(size, addr, priv);
- else if (dev->vendor == VEN_VIA_596B)
- ret = acpi_reg_read_via_596b(size, addr, priv);
- else if (dev->vendor == VEN_INTEL)
- ret = acpi_reg_read_intel(size, addr, priv);
- else if (dev->vendor == VEN_SMC)
- ret = acpi_reg_read_smc(size, addr, priv);
+ acpi_t *dev = (acpi_t *) priv;
- return ret;
+ dev->regs.reg_25 |= 0x02;
+ if (dev->regs.reg_26 & 0x02)
+ smi_raise();
}
static void
-acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv)
+acpi_reg_write_sis_5582(int size, uint16_t addr, uint8_t val, void *priv)
{
- const acpi_t *dev = (acpi_t *) priv;
-
- if (dev->vendor == VEN_ALI)
- acpi_reg_write_ali(size, addr, val, priv);
- else if (dev->vendor == VEN_VIA)
- acpi_reg_write_via(size, addr, val, priv);
- else if (dev->vendor == VEN_VIA_596B)
- acpi_reg_write_via_596b(size, addr, val, priv);
- else if (dev->vendor == VEN_INTEL)
- acpi_reg_write_intel(size, addr, val, priv);
- else if (dev->vendor == VEN_SMC)
- acpi_reg_write_smc(size, addr, val, priv);
-}
+ acpi_t *dev = (acpi_t *) priv;
+ int shift16;
+ int shift32;
+ uint8_t old;
-static uint32_t
-acpi_aux_reg_read_common(int size, uint16_t addr, void *priv)
-{
- const acpi_t *dev = (acpi_t *) priv;
+ addr &= 0x3f;
+#ifdef ENABLE_ACPI_LOG
+ if (size != 1)
+ acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val);
+#endif
+ shift16 = (addr & 1) << 3;
+ shift32 = (addr & 3) << 3;
+
+ switch (addr) {
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ dev->regs.reg_0c &= ~((val << shift32) & 0x007e);
+ break;
+ case 0x10:
+ dev->regs.enter_c2_ps = val;
+ break;
+ case 0x11:
+ dev->regs.enter_c3_ps = val;
+ break;
+ case 0x12:
+ dev->regs.reg_12 = val & 0x01;
+ break;
+ case 0x13:
+ dev->regs.reg_13 = val;
+ acpi_gp_timer_update(dev, (val != 0x00) && (dev->regs.reg_16 & 0x2000), val);
+ break;
+ case 0x14:
+ case 0x15:
+ dev->regs.reg_14 &= ~((val << shift32) & 0xff9f);
+ break;
+ case 0x16:
+ case 0x17:
+ dev->regs.reg_16 = ((dev->regs.reg_16 & ~(0xff << shift16)) | (val << shift16)) & 0xff1f;
+ break;
+ case 0x18:
+ case 0x19:
+ dev->regs.reg_18 = ((dev->regs.reg_18 & ~(0xff << shift16)) | (val << shift16)) & 0x07ff;
+ break;
+ case 0x1a:
+ case 0x1b:
+ dev->regs.reg_1a = ((dev->regs.reg_1a & ~(0xff << shift16)) | (val << shift16)) & 0x0387;
+ break;
+ case 0x1c:
+ case 0x1d:
+ dev->regs.reg_1c = ((dev->regs.reg_1c & ~(0xff << shift16)) | (val << shift16)) & 0x3f7f;
+ /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */
+ if (dev->regs.reg_1c & 0x0400) {
+ dev->regs.pmsts |= 0x20;
+ if (dev->regs.pmen & 0x20)
+ acpi_update_irq(dev);
+ }
+ break;
+ case 0x20:
+ /* SMI Command Port */
+ dev->regs.smi_cmd = val;
+ if (val == dev->regs.smi_en_val) {
+ dev->regs.reg_25 |= 0x08;
+ if (dev->regs.reg_26 & 0x08)
+ smi_raise();
+ } else if (val == dev->regs.smi_dis_val) {
+ dev->regs.reg_25 |= 0x10;
+ if (dev->regs.reg_26 & 0x10)
+ smi_raise();
+ }
+ break;
+ case 0x24:
+ dev->regs.reg_24 = val & 0x43;
+ break;
+ case 0x25:
+ dev->regs.reg_25 &= ~(val & 0x1f);
+ break;
+ case 0x26:
+ old = dev->regs.reg_26;
+ dev->regs.reg_26 = val & 0x3f;
+ if (!(old & 0x04) && (val & 0x04))
+ timer_on_auto(&dev->per_timer, 16000000.0);
+ else if ((old & 0x04) && !(val & 0x04))
+ timer_stop(&dev->per_timer);
+ break;
+ case 0x28:
+ dev->regs.smi_en_val = val;
+ break;
+ case 0x29:
+ dev->regs.smi_dis_val = val;
+ break;
+ case 0x2a:
+ dev->regs.mail_box = val;
+ break;
+ case 0x2b:
+ dev->regs.reg_2b = val & 0x01;
+ break;
+ default:
+ acpi_reg_write_common_regs(size, addr, val, priv);
+ /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */
+ if ((addr == 0x00) && !(dev->regs.pmsts & 0x20))
+ dev->regs.reg_1c &= ~0x0400;
+ else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) {
+ dev->regs.reg_25 |= 0x01;
+ if (dev->regs.reg_26 & 0x01)
+ acpi_raise_smi(dev, 1);
+ }
+ break;
+ }
+}
+
+void
+acpi_sis5595_pmu_event(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+
+ if (dev->vendor == VEN_SIS_5595_1997)
+ acpi_sis5595_smi_raise(dev);
+ else if (dev->regs.gpe_en & 0x00001000) {
+ dev->regs.gpe_sts |= 0x00001000;
+ acpi_sis5595_smi_raise(dev);
+ }
+}
+
+void
+acpi_sis5595_smbus_event(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+
+ if (dev->regs.gpe_en & 0x00000800) {
+ dev->regs.gpe_sts |= 0x00000800;
+ acpi_sis5595_smi_raise(dev);
+ }
+}
+
+void
+acpi_sis5595_software_smi(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+
+ if (dev->regs.leg_en & 0x01) {
+ dev->regs.leg_sts |= 0x01;
+ acpi_sis5595_smi_raise(dev);
+ }
+}
+
+static void
+acpi_reg_write_sis_5595(int size, uint16_t addr, uint8_t val, void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+ int shift16;
+ int shift32;
+ uint8_t old;
+ uint8_t do_smi = 0;
+
+ addr &= 0x3f;
+#ifdef ENABLE_ACPI_LOG
+ if (size != 1)
+ acpi_log("(%i) ACPI Write (%i) %02X: %02X\n", in_smm, size, addr, val);
+#endif
+ shift16 = (addr & 1) << 3;
+ shift32 = (addr & 3) << 3;
+
+ switch (addr) {
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ dev->regs.reg_0c &= ~((val << shift32) & 0x001e);
+ break;
+ case 0x10:
+ dev->regs.enter_c2_ps = val;
+ break;
+ case 0x11:
+ dev->regs.enter_c3_ps = val;
+ break;
+ case 0x12:
+ dev->regs.reg_12 = val & 0x01;
+ break;
+ case 0x13:
+ dev->regs.reg_13 = val;
+ /* Setting BIOS_RLS also sets GBL_STS and generates SMI. */
+ if (dev->regs.reg_13 & 0x02) {
+ dev->regs.pmsts |= 0x20;
+ if (dev->regs.pmen & 0x20)
+ acpi_update_irq(dev);
+ }
+ break;
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ dev->regs.gpe_sts &= ~((val << shift32) & 0xff03ffbf);
+ else
+ dev->regs.gpe_sts &= ~((val << shift32) & 0xff83ffff);
+ break;
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ dev->regs.gpe_en = ((dev->regs.gpe_en & ~(0xff << shift32)) | (val << shift32));
+ else
+ dev->regs.gpe_en = ((dev->regs.gpe_en & ~(0xff << shift32)) |
+ (val << shift32)) & 0xff83ffff;
+ break;
+ case 0x1c:
+ dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0xff << shift32)) | ((val & 0xff) << shift32));
+ if (!strcmp(machine_get_internal_name(), "m747") && (val & 0x10) &&
+ !(dev->regs.gpe_io & 0x00000010))
+ resetx86();
+ break;
+ case 0x1d:
+ dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0x0f << shift32)) | ((val & 0x0f) << shift32));
+ break;
+ case 0x1e:
+ dev->regs.gpe_pin = ((dev->regs.gpe_pin & ~(0x03 << shift32)) | ((val & 0x03) << shift32));
+ break;
+ case 0x1f:
+ dev->regs.gp_tmr = val;
+ acpi_gp_timer_update(dev, (val != 0x00) && (dev->regs.gpe_en & 0x00000400), val);
+ break;
+ case 0x20:
+ dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x9f << shift32)) | ((val & 0x9f) << shift32));
+ break;
+ case 0x21:
+ dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x0f << shift32)) | ((val & 0x0f) << shift32));
+ break;
+ case 0x22:
+ dev->regs.gpe_io = ((dev->regs.gpe_io & ~(0x03 << shift32)) | ((val & 0x03) << shift32));
+ break;
+ case 0x24:
+ dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0xbf << shift32)) | ((val & 0xbf) << shift32));
+ break;
+ case 0x25:
+ dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x0f << shift32)) | ((val & 0x0f) << shift32));
+ break;
+ case 0x26:
+ dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x03 << shift32)) | ((val & 0x03) << shift32));
+ break;
+ case 0x27:
+ dev->regs.gpe_pol = ((dev->regs.gpe_pol & ~(0x10 << shift32)) | ((val & 0x10) << shift32));
+ break;
+ case 0x28:
+ dev->regs.gpe_mul = ((dev->regs.gpe_mul & ~(0xf9 << shift16)) | ((val & 0xf9) << shift16));
+ break;
+ case 0x29:
+ dev->regs.gpe_mul = ((dev->regs.gpe_mul & ~(0x13 << shift16)) | ((val & 0x13) << shift16));
+ break;
+ case 0x2a:
+ case 0x2b:
+ dev->regs.gpe_ctl = ((dev->regs.gpe_ctl & ~(0xff << shift16)) | ((val & 0xff) << shift16));
+ break;
+ case 0x2c:
+ case 0x2d:
+ dev->regs.gpe_smi = ((dev->regs.gpe_smi & ~(0xff << shift16)) | ((val & 0xff) << shift16));
+ break;
+ case 0x2e:
+ case 0x2f:
+ dev->regs.gpe_rl = ((dev->regs.gpe_rl & ~(0xff << shift16)) | ((val & 0xff) << shift16));
+ break;
+ case 0x30:
+ dev->regs.leg_sts &= ~val;
+ break;
+ case 0x31:
+ old = dev->regs.leg_en;
+ dev->regs.leg_en = val;
+ if (!(old & 0x04) && (val & 0x04))
+ timer_on_auto(&dev->per_timer, 16000000.0);
+ else if ((old & 0x04) && !(val & 0x04))
+ timer_stop(&dev->per_timer);
+ break;
+ case 0x32:
+ if (dev->vendor == VEN_SIS_5595_1997) {
+ /* SMI Command Port */
+ dev->regs.smi_cmd = val;
+ if (val == dev->regs.smi_en_val) {
+ dev->regs.leg_sts |= 0x08;
+ if (dev->regs.leg_en & 0x08)
+ acpi_sis5595_smi_raise(dev);
+ } else if (val == dev->regs.smi_dis_val) {
+ dev->regs.leg_sts |= 0x10;
+ if (dev->regs.leg_en & 0x10)
+ acpi_sis5595_smi_raise(dev);
+ }
+ }
+ break;
+ case 0x33:
+ dev->regs.tst_ctl = val & 0x01;
+ break;
+ case 0x34:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ dev->regs.smi_en_val = val;
+ else
+ dev->regs.reg_34 = val;
+ break;
+ case 0x35:
+ if (dev->vendor == VEN_SIS_5595_1997)
+ dev->regs.smi_dis_val = val;
+ else {
+ /* SMI Command Port */
+ dev->regs.smi_cmd = val;
+ dev->regs.leg_sts |= 0x10;
+ if (dev->regs.leg_en & 0x10)
+ acpi_sis5595_smi_raise(dev);
+ }
+ break;
+ case 0x36:
+ dev->regs.mail_box = val;
+ break;
+ case 0x38:
+ if (dev->vendor == VEN_SIS_5595) {
+ dev->regs.index = val;
+ smbus_sis5595_write_index(dev->smbus, val);
+ }
+ break;
+ case 0x39:
+ if (dev->vendor == VEN_SIS_5595) {
+ dev->regs.reg_ff = val & 0x3f;
+ smbus_sis5595_write_data(dev->smbus, val);
+ if (val & 0x20) { /* Set GPIO5_STS of GPE_STS */
+ dev->regs.gpe_sts |= 0x00000008;
+ do_smi |= (dev->regs.gpe_en & 0x00000004);
+ } else if (val & 0x10) { /* Set GPIO10_STS of GPE_STS */
+ dev->regs.gpe_sts |= 0x00000004;
+ do_smi |= (dev->regs.gpe_en & 0x00000008);
+ } else if (val & 0x08) { /* Set RI_STS in GPE_STS */
+ dev->regs.gpe_sts |= 0x00000002;
+ do_smi |= (dev->regs.gpe_en & 0x00000002);
+ } else if (val & 0x04) /* Set WAK_STS of PM1_STS */
+ dev->regs.pmsts |= 0x8000;
+ else if (val & 0x02) { /* Set RTC_STS of PM1_STS */
+ dev->regs.pmsts |= 0x0400;
+ do_smi |= (dev->regs.pmen & 0x0400);
+ } else if (val & 0x01) { /* Set PWRBTN_STS of PM1_STS */
+ dev->regs.pmsts |= 0x0100;
+ do_smi |= (dev->regs.pmen & 0x0100);
+ }
+
+ if (do_smi)
+ acpi_sis5595_smi_raise(dev);
+ }
+ break;
+ default:
+ acpi_reg_write_common_regs(size, addr, val, priv);
+ /* Setting GBL_RLS also sets BIOS_STS and generates SMI. */
+ if ((addr == 0x00) && !(dev->regs.pmsts & 0x20))
+ dev->regs.reg_13 &= ~0x02;
+ else if ((addr == 0x04) && (dev->regs.pmcntrl & 0x0004)) {
+ dev->regs.leg_sts |= 0x01;
+ if (dev->regs.leg_en & 0x01)
+ acpi_sis5595_smi_raise(dev);
+ }
+ break;
+ }
+}
+
+static uint32_t
+acpi_reg_read_common(int size, uint16_t addr, void *priv)
+{
+ const acpi_t *dev = (acpi_t *) priv;
+ uint8_t ret = 0xff;
+
+ switch (dev->vendor) {
+ case VEN_ALI:
+ ret = acpi_reg_read_ali(size, addr, priv);
+ break;
+ case VEN_VIA:
+ ret = acpi_reg_read_via(size, addr, priv);
+ break;
+ case VEN_VIA_596B:
+ ret = acpi_reg_read_via_596b(size, addr, priv);
+ break;
+ case VEN_INTEL:
+ ret = acpi_reg_read_intel(size, addr, priv);
+ break;
+ case VEN_SMC:
+ ret = acpi_reg_read_smc(size, addr, priv);
+ break;
+ case VEN_SIS_5582:
+ ret = acpi_reg_read_sis_5582(size, addr, priv);
+ break;
+ case VEN_SIS_5595_1997:
+ case VEN_SIS_5595:
+ ret = acpi_reg_read_sis_5595(size, addr, priv);
+ break;
+ }
+
+ return ret;
+}
+
+static void
+acpi_reg_write_common(int size, uint16_t addr, uint8_t val, void *priv)
+{
+ const acpi_t *dev = (acpi_t *) priv;
+
+ switch (dev->vendor) {
+ case VEN_ALI:
+ acpi_reg_write_ali(size, addr, val, priv);
+ break;
+ case VEN_VIA:
+ acpi_reg_write_via(size, addr, val, priv);
+ break;
+ case VEN_VIA_596B:
+ acpi_reg_write_via_596b(size, addr, val, priv);
+ break;
+ case VEN_INTEL:
+ acpi_reg_write_intel(size, addr, val, priv);
+ break;
+ case VEN_SMC:
+ acpi_reg_write_smc(size, addr, val, priv);
+ break;
+ case VEN_SIS_5582:
+ acpi_reg_write_sis_5582(size, addr, val, priv);
+ break;
+ case VEN_SIS_5595_1997:
+ case VEN_SIS_5595:
+ acpi_reg_write_sis_5595(size, addr, val, priv);
+ break;
+ }
+}
+
+static uint32_t
+acpi_aux_reg_read_common(int size, uint16_t addr, void *priv)
+{
+ const acpi_t *dev = (acpi_t *) priv;
uint8_t ret = 0xff;
if (dev->vendor == VEN_SMC)
@@ -1396,6 +2113,9 @@ acpi_update_io_mapping(acpi_t *dev, uint32_t base, int chipset_en)
default:
case VEN_ALI:
case VEN_INTEL:
+ case VEN_SIS_5582:
+ case VEN_SIS_5595_1997:
+ case VEN_SIS_5595:
size = 0x040;
break;
case VEN_SMC:
@@ -1677,6 +2397,20 @@ acpi_reset(void *priv)
acpi_update_irq(dev);
dev->irq_state = 0;
+
+ timer_disable(&dev->gp_timer);
+
+ acpi_last_clock = 0ULL;
+ acpi_count = 0;
+
+ timer_disable(&dev->per_timer);
+
+ if ((dev->vendor == VEN_SIS_5595_1997) || (dev->vendor == VEN_SIS_5595)) {
+ dev->regs.reg_13 = 0x20;
+ dev->regs.gp_tmr = 0xff;
+ dev->regs.gpe_io = 0x00030b9f;
+ dev->regs.gpe_mul = 0x1001;
+ }
}
static void
@@ -1689,6 +2423,33 @@ acpi_speed_changed(void *priv)
if (timer_enabled)
timer_on_auto(&dev->timer, acpi_get_overflow_period(dev));
+
+ if ((dev->vendor & 0xffff) == 0x1039) {
+ if (timer_is_on(&dev->gp_timer)) {
+ timer_stop(&dev->gp_timer);
+
+ if (dev->vendor == VEN_SIS_5595_1997)
+ acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x20000000), acpi_count);
+ else if (dev->vendor == VEN_SIS_5595)
+ acpi_gp_timer_update(dev, (dev->regs.gpe_en & 0x00000400), acpi_count);
+ else
+ acpi_gp_timer_update(dev, (dev->regs.reg_16 & 0x2000), acpi_count);
+ }
+
+ if (timer_is_on(&dev->per_timer)) {
+ timer_stop(&dev->per_timer);
+
+ timer_on_auto(&dev->per_timer, 16000000.0);
+ }
+ }
+}
+
+void *
+acpi_get_smbus(void *priv)
+{
+ acpi_t *dev = (acpi_t *) priv;
+
+ return dev->smbus;
}
static void
@@ -1767,6 +2528,28 @@ acpi_init(const device_t *info)
dev->suspend_types[4] = SUS_SUSPEND;
break;
+ case VEN_SIS_5582:
+ dev->suspend_types[0] = SUS_SUSPEND; /* S1 */
+ dev->suspend_types[4] = SUS_POWER_OFF; /* S5 */
+
+ timer_add(&dev->gp_timer, acpi_gp_timer, dev, 0);
+ timer_add(&dev->per_timer, acpi_per_timer, dev, 0);
+ break;
+
+ case VEN_SIS_5595_1997:
+ case VEN_SIS_5595:
+ dev->suspend_types[1] = SUS_SUSPEND;
+ dev->suspend_types[2] = SUS_SUSPEND;
+ dev->suspend_types[3] = SUS_SUSPEND | SUS_NVR | SUS_RESET_CPU | SUS_RESET_PCI;
+ dev->suspend_types[4] = SUS_POWER_OFF;
+ dev->suspend_types[5] = SUS_POWER_OFF;
+
+ timer_add(&dev->gp_timer, acpi_gp_timer, dev, 0);
+ timer_add(&dev->per_timer, acpi_per_timer, dev, 0);
+
+ dev->smbus = device_add(&sis5595_smbus_device);
+ break;
+
default:
break;
}
@@ -1854,3 +2637,45 @@ const device_t acpi_smc_device = {
.force_redraw = NULL,
.config = NULL
};
+
+const device_t acpi_sis_5582_device = {
+ .name = "SiS 5582 ACPI",
+ .internal_name = "acpi_sis_5582",
+ .flags = DEVICE_PCI,
+ .local = VEN_SIS_5582,
+ .init = acpi_init,
+ .close = acpi_close,
+ .reset = acpi_reset,
+ { .available = NULL },
+ .speed_changed = acpi_speed_changed,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t acpi_sis_5595_1997_device = {
+ .name = "SiS 5595 (1997) ACPI",
+ .internal_name = "acpi_sis_5595_1997",
+ .flags = DEVICE_PCI,
+ .local = VEN_SIS_5595_1997,
+ .init = acpi_init,
+ .close = acpi_close,
+ .reset = acpi_reset,
+ { .available = NULL },
+ .speed_changed = acpi_speed_changed,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t acpi_sis_5595_device = {
+ .name = "SiS 5595 ACPI",
+ .internal_name = "acpi_sis_5595",
+ .flags = DEVICE_PCI,
+ .local = VEN_SIS_5595,
+ .init = acpi_init,
+ .close = acpi_close,
+ .reset = acpi_reset,
+ { .available = NULL },
+ .speed_changed = acpi_speed_changed,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/cJSON.c b/src/cJSON.c
new file mode 100644
index 0000000000..4e4979e99d
--- /dev/null
+++ b/src/cJSON.c
@@ -0,0 +1,3129 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef ENABLE_LOCALES
+#include
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
+#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
+#define false ((cJSON_bool)0)
+
+/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
+#ifndef isinf
+#define isinf(d) (isnan((d - d)) && !isnan(d))
+#endif
+#ifndef isnan
+#define isnan(d) (d != d)
+#endif
+
+#ifndef NAN
+#ifdef _WIN32
+#define NAN sqrt(-1.0)
+#else
+#define NAN 0.0/0.0
+#endif
+#endif
+
+typedef struct {
+ const unsigned char *json;
+ size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+ return (const char*) (global_error.json + global_error.position);
+}
+
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
+{
+ if (!cJSON_IsString(item))
+ {
+ return NULL;
+ }
+
+ return item->valuestring;
+}
+
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
+{
+ if (!cJSON_IsNumber(item))
+ {
+ return (double) NAN;
+ }
+
+ return item->valuedouble;
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 17)
+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char*) cJSON_Version(void)
+{
+ static char version[15];
+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+ return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
+{
+ if ((string1 == NULL) || (string2 == NULL))
+ {
+ return 1;
+ }
+
+ if (string1 == string2)
+ {
+ return 0;
+ }
+
+ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
+ {
+ if (*string1 == '\0')
+ {
+ return 0;
+ }
+ }
+
+ return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks
+{
+ void *(CJSON_CDECL *allocate)(size_t size);
+ void (CJSON_CDECL *deallocate)(void *pointer);
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+ return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+ free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+ return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+/* strlen of character literals resolved at compile time */
+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
+
+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
+{
+ size_t length = 0;
+ unsigned char *copy = NULL;
+
+ if (string == NULL)
+ {
+ return NULL;
+ }
+
+ length = strlen((const char*)string) + sizeof("");
+ copy = (unsigned char*)hooks->allocate(length);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ memcpy(copy, string, length);
+
+ return copy;
+}
+
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (hooks == NULL)
+ {
+ /* Reset hooks */
+ global_hooks.allocate = malloc;
+ global_hooks.deallocate = free;
+ global_hooks.reallocate = realloc;
+ return;
+ }
+
+ global_hooks.allocate = malloc;
+ if (hooks->malloc_fn != NULL)
+ {
+ global_hooks.allocate = hooks->malloc_fn;
+ }
+
+ global_hooks.deallocate = free;
+ if (hooks->free_fn != NULL)
+ {
+ global_hooks.deallocate = hooks->free_fn;
+ }
+
+ /* use realloc only if both free and malloc are used */
+ global_hooks.reallocate = NULL;
+ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
+ {
+ global_hooks.reallocate = realloc;
+ }
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
+{
+ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
+ if (node)
+ {
+ memset(node, '\0', sizeof(cJSON));
+ }
+
+ return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+ cJSON *next = NULL;
+ while (item != NULL)
+ {
+ next = item->next;
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL))
+ {
+ cJSON_Delete(item->child);
+ }
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
+ {
+ global_hooks.deallocate(item->valuestring);
+ }
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ global_hooks.deallocate(item->string);
+ }
+ global_hooks.deallocate(item);
+ item = next;
+ }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+ struct lconv *lconv = localeconv();
+ return (unsigned char) lconv->decimal_point[0];
+#else
+ return '.';
+#endif
+}
+
+typedef struct
+{
+ const unsigned char *content;
+ size_t length;
+ size_t offset;
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+ internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
+{
+ double number = 0;
+ unsigned char *after_end = NULL;
+ unsigned char number_c_string[64];
+ unsigned char decimal_point = get_decimal_point();
+ size_t i = 0;
+
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
+ {
+ return false;
+ }
+
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
+ * of the current locale (for strtod)
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
+ {
+ switch (buffer_at_offset(input_buffer)[i])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case 'e':
+ case 'E':
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
+ break;
+
+ case '.':
+ number_c_string[i] = decimal_point;
+ break;
+
+ default:
+ goto loop_end;
+ }
+ }
+loop_end:
+ number_c_string[i] = '\0';
+
+ number = strtod((const char*)number_c_string, (char**)&after_end);
+ if (number_c_string == after_end)
+ {
+ return false; /* parse_error */
+ }
+
+ item->valuedouble = number;
+
+ /* use saturation in case of overflow */
+ if (number >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (number <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)number;
+ }
+
+ item->type = cJSON_Number;
+
+ input_buffer->offset += (size_t)(after_end - number_c_string);
+ return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+ if (number >= INT_MAX)
+ {
+ object->valueint = INT_MAX;
+ }
+ else if (number <= (double)INT_MIN)
+ {
+ object->valueint = INT_MIN;
+ }
+ else
+ {
+ object->valueint = (int)number;
+ }
+
+ return object->valuedouble = number;
+}
+
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
+{
+ char *copy = NULL;
+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
+ if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
+ {
+ return NULL;
+ }
+ /* return NULL if the object is corrupted */
+ if (object->valuestring == NULL)
+ {
+ return NULL;
+ }
+ if (strlen(valuestring) <= strlen(object->valuestring))
+ {
+ strcpy(object->valuestring, valuestring);
+ return object->valuestring;
+ }
+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ if (object->valuestring != NULL)
+ {
+ cJSON_free(object->valuestring);
+ }
+ object->valuestring = copy;
+
+ return copy;
+}
+
+typedef struct
+{
+ unsigned char *buffer;
+ size_t length;
+ size_t offset;
+ size_t depth; /* current nesting depth (for formatted printing) */
+ cJSON_bool noalloc;
+ cJSON_bool format; /* is this print a formatted print */
+ internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char* ensure(printbuffer * const p, size_t needed)
+{
+ unsigned char *newbuffer = NULL;
+ size_t newsize = 0;
+
+ if ((p == NULL) || (p->buffer == NULL))
+ {
+ return NULL;
+ }
+
+ if ((p->length > 0) && (p->offset >= p->length))
+ {
+ /* make sure that offset is valid */
+ return NULL;
+ }
+
+ if (needed > INT_MAX)
+ {
+ /* sizes bigger than INT_MAX are currently not supported */
+ return NULL;
+ }
+
+ needed += p->offset + 1;
+ if (needed <= p->length)
+ {
+ return p->buffer + p->offset;
+ }
+
+ if (p->noalloc) {
+ return NULL;
+ }
+
+ /* calculate new buffer size */
+ if (needed > (INT_MAX / 2))
+ {
+ /* overflow of int, use INT_MAX if possible */
+ if (needed <= INT_MAX)
+ {
+ newsize = INT_MAX;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ newsize = needed * 2;
+ }
+
+ if (p->hooks.reallocate != NULL)
+ {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
+ if (newbuffer == NULL)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ }
+ else
+ {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char*)p->hooks.allocate(newsize);
+ if (!newbuffer)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+
+ memcpy(newbuffer, p->buffer, p->offset + 1);
+ p->hooks.deallocate(p->buffer);
+ }
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer * const buffer)
+{
+ const unsigned char *buffer_pointer = NULL;
+ if ((buffer == NULL) || (buffer->buffer == NULL))
+ {
+ return;
+ }
+ buffer_pointer = buffer->buffer + buffer->offset;
+
+ buffer->offset += strlen((const char*)buffer_pointer);
+}
+
+/* securely comparison of floating-point variables */
+static cJSON_bool compare_double(double a, double b)
+{
+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ double d = item->valuedouble;
+ int length = 0;
+ size_t i = 0;
+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
+ unsigned char decimal_point = get_decimal_point();
+ double test = 0.0;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* This checks for NaN and Infinity */
+ if (isnan(d) || isinf(d))
+ {
+ length = sprintf((char*)number_buffer, "null");
+ }
+ else if(d == (double)item->valueint)
+ {
+ length = sprintf((char*)number_buffer, "%d", item->valueint);
+ }
+ else
+ {
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+ length = sprintf((char*)number_buffer, "%1.15g", d);
+
+ /* Check whether the original double can be recovered */
+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
+ {
+ /* If not, print with 17 decimal places of precision */
+ length = sprintf((char*)number_buffer, "%1.17g", d);
+ }
+ }
+
+ /* sprintf failed or buffer overrun occurred */
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
+ {
+ return false;
+ }
+
+ /* reserve appropriate space in the output */
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ /* copy the printed number to the output and replace locale
+ * dependent decimal point with '.' */
+ for (i = 0; i < ((size_t)length); i++)
+ {
+ if (number_buffer[i] == decimal_point)
+ {
+ output_pointer[i] = '.';
+ continue;
+ }
+
+ output_pointer[i] = number_buffer[i];
+ }
+ output_pointer[i] = '\0';
+
+ output_buffer->offset += (size_t)length;
+
+ return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char * const input)
+{
+ unsigned int h = 0;
+ size_t i = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ /* parse digit */
+ if ((input[i] >= '0') && (input[i] <= '9'))
+ {
+ h += (unsigned int) input[i] - '0';
+ }
+ else if ((input[i] >= 'A') && (input[i] <= 'F'))
+ {
+ h += (unsigned int) 10 + input[i] - 'A';
+ }
+ else if ((input[i] >= 'a') && (input[i] <= 'f'))
+ {
+ h += (unsigned int) 10 + input[i] - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+ if (i < 3)
+ {
+ /* shift left to make place for the next nibble */
+ h = h << 4;
+ }
+ }
+
+ return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+ * A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
+{
+ long unsigned int codepoint = 0;
+ unsigned int first_code = 0;
+ const unsigned char *first_sequence = input_pointer;
+ unsigned char utf8_length = 0;
+ unsigned char utf8_position = 0;
+ unsigned char sequence_length = 0;
+ unsigned char first_byte_mark = 0;
+
+ if ((input_end - first_sequence) < 6)
+ {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ /* get the first utf16 sequence */
+ first_code = parse_hex4(first_sequence + 2);
+
+ /* check that the code is valid */
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
+ {
+ goto fail;
+ }
+
+ /* UTF16 surrogate pair */
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
+ {
+ const unsigned char *second_sequence = first_sequence + 6;
+ unsigned int second_code = 0;
+ sequence_length = 12; /* \uXXXX\uXXXX */
+
+ if ((input_end - second_sequence) < 6)
+ {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
+ {
+ /* missing second half of the surrogate pair */
+ goto fail;
+ }
+
+ /* get the second utf16 sequence */
+ second_code = parse_hex4(second_sequence + 2);
+ /* check that the code is valid */
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF))
+ {
+ /* invalid second half of the surrogate pair */
+ goto fail;
+ }
+
+
+ /* calculate the unicode codepoint from the surrogate pair */
+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+ }
+ else
+ {
+ sequence_length = 6; /* \uXXXX */
+ codepoint = first_code;
+ }
+
+ /* encode as UTF-8
+ * takes at maximum 4 bytes to encode:
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ if (codepoint < 0x80)
+ {
+ /* normal ascii, encoding 0xxxxxxx */
+ utf8_length = 1;
+ }
+ else if (codepoint < 0x800)
+ {
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
+ utf8_length = 2;
+ first_byte_mark = 0xC0; /* 11000000 */
+ }
+ else if (codepoint < 0x10000)
+ {
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 3;
+ first_byte_mark = 0xE0; /* 11100000 */
+ }
+ else if (codepoint <= 0x10FFFF)
+ {
+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 4;
+ first_byte_mark = 0xF0; /* 11110000 */
+ }
+ else
+ {
+ /* invalid unicode codepoint */
+ goto fail;
+ }
+
+ /* encode as utf8 */
+ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
+ {
+ /* 10xxxxxx */
+ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
+ codepoint >>= 6;
+ }
+ /* encode first byte */
+ if (utf8_length > 1)
+ {
+ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
+ }
+ else
+ {
+ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
+ }
+
+ *output_pointer += utf8_length;
+
+ return sequence_length;
+
+fail:
+ return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
+{
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+ unsigned char *output_pointer = NULL;
+ unsigned char *output = NULL;
+
+ /* not a string */
+ if (buffer_at_offset(input_buffer)[0] != '\"')
+ {
+ goto fail;
+ }
+
+ {
+ /* calculate approximate size of the output (overestimate) */
+ size_t allocation_length = 0;
+ size_t skipped_bytes = 0;
+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
+ {
+ /* is escape sequence */
+ if (input_end[0] == '\\')
+ {
+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
+ {
+ /* prevent buffer overflow when last input character is a backslash */
+ goto fail;
+ }
+ skipped_bytes++;
+ input_end++;
+ }
+ input_end++;
+ }
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
+ {
+ goto fail; /* string ended unexpectedly */
+ }
+
+ /* This is at most how much we need for the output */
+ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+ if (output == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+ }
+
+ output_pointer = output;
+ /* loop through the string literal */
+ while (input_pointer < input_end)
+ {
+ if (*input_pointer != '\\')
+ {
+ *output_pointer++ = *input_pointer++;
+ }
+ /* escape sequence */
+ else
+ {
+ unsigned char sequence_length = 2;
+ if ((input_end - input_pointer) < 1)
+ {
+ goto fail;
+ }
+
+ switch (input_pointer[1])
+ {
+ case 'b':
+ *output_pointer++ = '\b';
+ break;
+ case 'f':
+ *output_pointer++ = '\f';
+ break;
+ case 'n':
+ *output_pointer++ = '\n';
+ break;
+ case 'r':
+ *output_pointer++ = '\r';
+ break;
+ case 't':
+ *output_pointer++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *output_pointer++ = input_pointer[1];
+ break;
+
+ /* UTF-16 literal */
+ case 'u':
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+ if (sequence_length == 0)
+ {
+ /* failed to convert UTF16-literal to UTF-8 */
+ goto fail;
+ }
+ break;
+
+ default:
+ goto fail;
+ }
+ input_pointer += sequence_length;
+ }
+ }
+
+ /* zero terminate the output */
+ *output_pointer = '\0';
+
+ item->type = cJSON_String;
+ item->valuestring = (char*)output;
+
+ input_buffer->offset = (size_t) (input_end - input_buffer->content);
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (output != NULL)
+ {
+ input_buffer->hooks.deallocate(output);
+ }
+
+ if (input_pointer != NULL)
+ {
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+ }
+
+ return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
+{
+ const unsigned char *input_pointer = NULL;
+ unsigned char *output = NULL;
+ unsigned char *output_pointer = NULL;
+ size_t output_length = 0;
+ /* numbers of additional characters needed for escaping */
+ size_t escape_characters = 0;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* empty string */
+ if (input == NULL)
+ {
+ output = ensure(output_buffer, sizeof("\"\""));
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "\"\"");
+
+ return true;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (input_pointer = input; *input_pointer; input_pointer++)
+ {
+ switch (*input_pointer)
+ {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ /* one character escape sequence */
+ escape_characters++;
+ break;
+ default:
+ if (*input_pointer < 32)
+ {
+ /* UTF-16 escape sequence uXXXX */
+ escape_characters += 5;
+ }
+ break;
+ }
+ }
+ output_length = (size_t)(input_pointer - input) + escape_characters;
+
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
+ if (output == NULL)
+ {
+ return false;
+ }
+
+ /* no characters have to be escaped */
+ if (escape_characters == 0)
+ {
+ output[0] = '\"';
+ memcpy(output + 1, input, output_length);
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+ }
+
+ output[0] = '\"';
+ output_pointer = output + 1;
+ /* copy the string */
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
+ {
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
+ {
+ /* normal character, copy */
+ *output_pointer = *input_pointer;
+ }
+ else
+ {
+ /* character needs to be escaped */
+ *output_pointer++ = '\\';
+ switch (*input_pointer)
+ {
+ case '\\':
+ *output_pointer = '\\';
+ break;
+ case '\"':
+ *output_pointer = '\"';
+ break;
+ case '\b':
+ *output_pointer = 'b';
+ break;
+ case '\f':
+ *output_pointer = 'f';
+ break;
+ case '\n':
+ *output_pointer = 'n';
+ break;
+ case '\r':
+ *output_pointer = 'r';
+ break;
+ case '\t':
+ *output_pointer = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf((char*)output_pointer, "u%04x", *input_pointer);
+ output_pointer += 4;
+ break;
+ }
+ }
+ }
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
+{
+ return print_string_ptr((unsigned char*)item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL))
+ {
+ return NULL;
+ }
+
+ if (cannot_access_at_index(buffer, 0))
+ {
+ return buffer;
+ }
+
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
+ {
+ buffer->offset++;
+ }
+
+ if (buffer->offset == buffer->length)
+ {
+ buffer->offset--;
+ }
+
+ return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
+ {
+ return NULL;
+ }
+
+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
+ {
+ buffer->offset += 3;
+ }
+
+ return buffer;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ size_t buffer_length;
+
+ if (NULL == value)
+ {
+ return NULL;
+ }
+
+ /* Adding null character size due to require_null_terminated. */
+ buffer_length = strlen(value) + sizeof("");
+
+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
+ cJSON *item = NULL;
+
+ /* reset error position */
+ global_error.json = NULL;
+ global_error.position = 0;
+
+ if (value == NULL || 0 == buffer_length)
+ {
+ goto fail;
+ }
+
+ buffer.content = (const unsigned char*)value;
+ buffer.length = buffer_length;
+ buffer.offset = 0;
+ buffer.hooks = global_hooks;
+
+ item = cJSON_New_Item(&global_hooks);
+ if (item == NULL) /* memory fail */
+ {
+ goto fail;
+ }
+
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
+ {
+ /* parse failure. ep is set. */
+ goto fail;
+ }
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated)
+ {
+ buffer_skip_whitespace(&buffer);
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
+ {
+ goto fail;
+ }
+ }
+ if (return_parse_end)
+ {
+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
+ }
+
+ return item;
+
+fail:
+ if (item != NULL)
+ {
+ cJSON_Delete(item);
+ }
+
+ if (value != NULL)
+ {
+ error local_error;
+ local_error.json = (const unsigned char*)value;
+ local_error.position = 0;
+
+ if (buffer.offset < buffer.length)
+ {
+ local_error.position = buffer.offset;
+ }
+ else if (buffer.length > 0)
+ {
+ local_error.position = buffer.length - 1;
+ }
+
+ if (return_parse_end != NULL)
+ {
+ *return_parse_end = (const char*)local_error.json + local_error.position;
+ }
+
+ global_error = local_error;
+ }
+
+ return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
+{
+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
+}
+
+#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
+
+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
+{
+ static const size_t default_buffer_size = 256;
+ printbuffer buffer[1];
+ unsigned char *printed = NULL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* create buffer */
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+ buffer->length = default_buffer_size;
+ buffer->format = format;
+ buffer->hooks = *hooks;
+ if (buffer->buffer == NULL)
+ {
+ goto fail;
+ }
+
+ /* print the value */
+ if (!print_value(item, buffer))
+ {
+ goto fail;
+ }
+ update_offset(buffer);
+
+ /* check if reallocate is available */
+ if (hooks->reallocate != NULL)
+ {
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ buffer->buffer = NULL;
+ }
+ else /* otherwise copy the JSON over to a new buffer */
+ {
+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
+ if (printed == NULL)
+ {
+ goto fail;
+ }
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+ printed[buffer->offset] = '\0'; /* just to be sure */
+
+ /* free the buffer */
+ hooks->deallocate(buffer->buffer);
+ }
+
+ return printed;
+
+fail:
+ if (buffer->buffer != NULL)
+ {
+ hooks->deallocate(buffer->buffer);
+ }
+
+ if (printed != NULL)
+ {
+ hooks->deallocate(printed);
+ }
+
+ return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+ return (char*)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+ return (char*)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if (prebuffer < 0)
+ {
+ return NULL;
+ }
+
+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
+ if (!p.buffer)
+ {
+ return NULL;
+ }
+
+ p.length = (size_t)prebuffer;
+ p.offset = 0;
+ p.noalloc = false;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ if (!print_value(item, &p))
+ {
+ global_hooks.deallocate(p.buffer);
+ return NULL;
+ }
+
+ return (char*)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if ((length < 0) || (buffer == NULL))
+ {
+ return false;
+ }
+
+ p.buffer = (unsigned char*)buffer;
+ p.length = (size_t)length;
+ p.offset = 0;
+ p.noalloc = true;
+ p.format = format;
+ p.hooks = global_hooks;
+
+ return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
+{
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
+ {
+ return false; /* no input */
+ }
+
+ /* parse the different types of values */
+ /* null */
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
+ {
+ item->type = cJSON_NULL;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* false */
+ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
+ {
+ item->type = cJSON_False;
+ input_buffer->offset += 5;
+ return true;
+ }
+ /* true */
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
+ {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* string */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
+ {
+ return parse_string(item, input_buffer);
+ }
+ /* number */
+ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
+ {
+ return parse_number(item, input_buffer);
+ }
+ /* array */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
+ {
+ return parse_array(item, input_buffer);
+ }
+ /* object */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
+ {
+ return parse_object(item, input_buffer);
+ }
+
+ return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output = NULL;
+
+ if ((item == NULL) || (output_buffer == NULL))
+ {
+ return false;
+ }
+
+ switch ((item->type) & 0xFF)
+ {
+ case cJSON_NULL:
+ output = ensure(output_buffer, 5);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "null");
+ return true;
+
+ case cJSON_False:
+ output = ensure(output_buffer, 6);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "false");
+ return true;
+
+ case cJSON_True:
+ output = ensure(output_buffer, 5);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "true");
+ return true;
+
+ case cJSON_Number:
+ return print_number(item, output_buffer);
+
+ case cJSON_Raw:
+ {
+ size_t raw_length = 0;
+ if (item->valuestring == NULL)
+ {
+ return false;
+ }
+
+ raw_length = strlen(item->valuestring) + sizeof("");
+ output = ensure(output_buffer, raw_length);
+ if (output == NULL)
+ {
+ return false;
+ }
+ memcpy(output, item->valuestring, raw_length);
+ return true;
+ }
+
+ case cJSON_String:
+ return print_string(item, output_buffer);
+
+ case cJSON_Array:
+ return print_array(item, output_buffer);
+
+ case cJSON_Object:
+ return print_object(item, output_buffer);
+
+ default:
+ return false;
+ }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* head of the linked list */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+ {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (buffer_at_offset(input_buffer)[0] != '[')
+ {
+ /* not an array */
+ goto fail;
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
+ {
+ /* empty array */
+ goto success;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0))
+ {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do
+ {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL)
+ {
+ /* start the linked list */
+ current_item = head = new_item;
+ }
+ else
+ {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse next value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ }
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
+ {
+ goto fail; /* expected end of array */
+ }
+
+success:
+ input_buffer->depth--;
+
+ if (head != NULL) {
+ head->prev = current_item;
+ }
+
+ item->type = cJSON_Array;
+ item->child = head;
+
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (head != NULL)
+ {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_element = item->child;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* Compose the output array. */
+ /* opening square bracket */
+ output_pointer = ensure(output_buffer, 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ *output_pointer = '[';
+ output_buffer->offset++;
+ output_buffer->depth++;
+
+ while (current_element != NULL)
+ {
+ if (!print_value(current_element, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+ if (current_element->next)
+ {
+ length = (size_t) (output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ',';
+ if(output_buffer->format)
+ {
+ *output_pointer++ = ' ';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+ }
+ current_element = current_element->next;
+ }
+
+ output_pointer = ensure(output_buffer, 2);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ']';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* linked list head */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+ {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
+ {
+ goto fail; /* not an object */
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
+ {
+ goto success; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0))
+ {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do
+ {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL)
+ {
+ /* start the linked list */
+ current_item = head = new_item;
+ }
+ else
+ {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse the name of the child */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_string(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse name */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* swap valuestring and string, because we parsed the name */
+ current_item->string = current_item->valuestring;
+ current_item->valuestring = NULL;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
+ {
+ goto fail; /* invalid object */
+ }
+
+ /* parse the value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ }
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
+ {
+ goto fail; /* expected end of object */
+ }
+
+success:
+ input_buffer->depth--;
+
+ if (head != NULL) {
+ head->prev = current_item;
+ }
+
+ item->type = cJSON_Object;
+ item->child = head;
+
+ input_buffer->offset++;
+ return true;
+
+fail:
+ if (head != NULL)
+ {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_item = item->child;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* Compose the output: */
+ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ *output_pointer++ = '{';
+ output_buffer->depth++;
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\n';
+ }
+ output_buffer->offset += length;
+
+ while (current_item)
+ {
+ if (output_buffer->format)
+ {
+ size_t i;
+ output_pointer = ensure(output_buffer, output_buffer->depth);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ for (i = 0; i < output_buffer->depth; i++)
+ {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += output_buffer->depth;
+ }
+
+ /* print key */
+ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ length = (size_t) (output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ':';
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += length;
+
+ /* print value */
+ if (!print_value(current_item, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ /* print comma if not last */
+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ if (current_item->next)
+ {
+ *output_pointer++ = ',';
+ }
+
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\n';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+
+ current_item = current_item->next;
+ }
+
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ if (output_buffer->format)
+ {
+ size_t i;
+ for (i = 0; i < (output_buffer->depth - 1); i++)
+ {
+ *output_pointer++ = '\t';
+ }
+ }
+ *output_pointer++ = '}';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+ cJSON *child = NULL;
+ size_t size = 0;
+
+ if (array == NULL)
+ {
+ return 0;
+ }
+
+ child = array->child;
+
+ while(child != NULL)
+ {
+ size++;
+ child = child->next;
+ }
+
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+ return (int)size;
+}
+
+static cJSON* get_array_item(const cJSON *array, size_t index)
+{
+ cJSON *current_child = NULL;
+
+ if (array == NULL)
+ {
+ return NULL;
+ }
+
+ current_child = array->child;
+ while ((current_child != NULL) && (index > 0))
+ {
+ index--;
+ current_child = current_child->next;
+ }
+
+ return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+ if (index < 0)
+ {
+ return NULL;
+ }
+
+ return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
+{
+ cJSON *current_element = NULL;
+
+ if ((object == NULL) || (name == NULL))
+ {
+ return NULL;
+ }
+
+ current_element = object->child;
+ if (case_sensitive)
+ {
+ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
+ {
+ current_element = current_element->next;
+ }
+ }
+ else
+ {
+ while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
+ {
+ current_element = current_element->next;
+ }
+ }
+
+ if ((current_element == NULL) || (current_element->string == NULL)) {
+ return NULL;
+ }
+
+ return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
+{
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
+{
+ cJSON *reference = NULL;
+ if (item == NULL)
+ {
+ return NULL;
+ }
+
+ reference = cJSON_New_Item(hooks);
+ if (reference == NULL)
+ {
+ return NULL;
+ }
+
+ memcpy(reference, item, sizeof(cJSON));
+ reference->string = NULL;
+ reference->type |= cJSON_IsReference;
+ reference->next = reference->prev = NULL;
+ return reference;
+}
+
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
+{
+ cJSON *child = NULL;
+
+ if ((item == NULL) || (array == NULL) || (array == item))
+ {
+ return false;
+ }
+
+ child = array->child;
+ /*
+ * To find the last item in array quickly, we use prev in array
+ */
+ if (child == NULL)
+ {
+ /* list is empty, start new one */
+ array->child = item;
+ item->prev = item;
+ item->next = NULL;
+ }
+ else
+ {
+ /* append to the end */
+ if (child->prev)
+ {
+ suffix_object(child->prev, item);
+ array->child->prev = item;
+ }
+ }
+
+ return true;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ return add_item_to_array(array, item);
+}
+
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+ return (void*)string;
+}
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic pop
+#endif
+
+
+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+ char *new_key = NULL;
+ int new_type = cJSON_Invalid;
+
+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
+ {
+ return false;
+ }
+
+ if (constant_key)
+ {
+ new_key = (char*)cast_away_const(string);
+ new_type = item->type | cJSON_StringIsConst;
+ }
+ else
+ {
+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
+ if (new_key == NULL)
+ {
+ return false;
+ }
+
+ new_type = item->type & ~cJSON_StringIsConst;
+ }
+
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ hooks->deallocate(item->string);
+ }
+
+ item->string = new_key;
+ item->type = new_type;
+
+ return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ if (array == NULL)
+ {
+ return false;
+ }
+
+ return add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ if ((object == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+ cJSON *null = cJSON_CreateNull();
+ if (add_item_to_object(object, name, null, &global_hooks, false))
+ {
+ return null;
+ }
+
+ cJSON_Delete(null);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+ cJSON *true_item = cJSON_CreateTrue();
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
+ {
+ return true_item;
+ }
+
+ cJSON_Delete(true_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+ cJSON *false_item = cJSON_CreateFalse();
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
+ {
+ return false_item;
+ }
+
+ cJSON_Delete(false_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+ cJSON *bool_item = cJSON_CreateBool(boolean);
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+ {
+ return bool_item;
+ }
+
+ cJSON_Delete(bool_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+ cJSON *number_item = cJSON_CreateNumber(number);
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
+ {
+ return number_item;
+ }
+
+ cJSON_Delete(number_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+ cJSON *string_item = cJSON_CreateString(string);
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
+ {
+ return string_item;
+ }
+
+ cJSON_Delete(string_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
+{
+ cJSON *raw_item = cJSON_CreateRaw(raw);
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+ {
+ return raw_item;
+ }
+
+ cJSON_Delete(raw_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+ cJSON *object_item = cJSON_CreateObject();
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
+ {
+ return object_item;
+ }
+
+ cJSON_Delete(object_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
+{
+ cJSON *array = cJSON_CreateArray();
+ if (add_item_to_object(object, name, array, &global_hooks, false))
+ {
+ return array;
+ }
+
+ cJSON_Delete(array);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
+{
+ if ((parent == NULL) || (item == NULL))
+ {
+ return NULL;
+ }
+
+ if (item != parent->child)
+ {
+ /* not the first element */
+ item->prev->next = item->next;
+ }
+ if (item->next != NULL)
+ {
+ /* not the last element */
+ item->next->prev = item->prev;
+ }
+
+ if (item == parent->child)
+ {
+ /* first element */
+ parent->child = item->next;
+ }
+ else if (item->next == NULL)
+ {
+ /* last element */
+ parent->child->prev = item->prev;
+ }
+
+ /* make sure the detached item doesn't point anywhere anymore */
+ item->prev = NULL;
+ item->next = NULL;
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ if (which < 0)
+ {
+ return NULL;
+ }
+
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *after_inserted = NULL;
+
+ if (which < 0 || newitem == NULL)
+ {
+ return false;
+ }
+
+ after_inserted = get_array_item(array, (size_t)which);
+ if (after_inserted == NULL)
+ {
+ return add_item_to_array(array, newitem);
+ }
+
+ if (after_inserted != array->child && after_inserted->prev == NULL) {
+ /* return false if after_inserted is a corrupted array item */
+ return false;
+ }
+
+ newitem->next = after_inserted;
+ newitem->prev = after_inserted->prev;
+ after_inserted->prev = newitem;
+ if (after_inserted == array->child)
+ {
+ array->child = newitem;
+ }
+ else
+ {
+ newitem->prev->next = newitem;
+ }
+ return true;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
+{
+ if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
+ {
+ return false;
+ }
+
+ if (replacement == item)
+ {
+ return true;
+ }
+
+ replacement->next = item->next;
+ replacement->prev = item->prev;
+
+ if (replacement->next != NULL)
+ {
+ replacement->next->prev = replacement;
+ }
+ if (parent->child == item)
+ {
+ if (parent->child->prev == parent->child)
+ {
+ replacement->prev = replacement;
+ }
+ parent->child = replacement;
+ }
+ else
+ { /*
+ * To find the last item in array quickly, we use prev in array.
+ * We can't modify the last item's next pointer where this item was the parent's child
+ */
+ if (replacement->prev != NULL)
+ {
+ replacement->prev->next = replacement;
+ }
+ if (replacement->next == NULL)
+ {
+ parent->child->prev = replacement;
+ }
+ }
+
+ item->next = NULL;
+ item->prev = NULL;
+ cJSON_Delete(item);
+
+ return true;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ if (which < 0)
+ {
+ return false;
+ }
+
+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
+{
+ if ((replacement == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ /* replace the name in the replacement */
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
+ {
+ cJSON_free(replacement->string);
+ }
+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if (replacement->string == NULL)
+ {
+ return false;
+ }
+
+ replacement->type &= ~cJSON_StringIsConst;
+
+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+ return replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+{
+ return replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = boolean ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+
+ /* use saturation in case of overflow */
+ if (num >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (num <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)num;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_String;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL)
+ {
+ item->type = cJSON_String | cJSON_IsReference;
+ item->valuestring = (char*)cast_away_const(string);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Object | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Array | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Raw;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type=cJSON_Array;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item)
+ {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber((double)numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (strings == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateString(strings[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p,n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+/* Duplication */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+ cJSON *newitem = NULL;
+ cJSON *child = NULL;
+ cJSON *next = NULL;
+ cJSON *newchild = NULL;
+
+ /* Bail on bad ptr */
+ if (!item)
+ {
+ goto fail;
+ }
+ /* Create new item */
+ newitem = cJSON_New_Item(&global_hooks);
+ if (!newitem)
+ {
+ goto fail;
+ }
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference);
+ newitem->valueint = item->valueint;
+ newitem->valuedouble = item->valuedouble;
+ if (item->valuestring)
+ {
+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
+ if (!newitem->valuestring)
+ {
+ goto fail;
+ }
+ }
+ if (item->string)
+ {
+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
+ if (!newitem->string)
+ {
+ goto fail;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse)
+ {
+ return newitem;
+ }
+ /* Walk the ->next chain for the child. */
+ child = item->child;
+ while (child != NULL)
+ {
+ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild)
+ {
+ goto fail;
+ }
+ if (next != NULL)
+ {
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ next->next = newchild;
+ newchild->prev = next;
+ next = newchild;
+ }
+ else
+ {
+ /* Set newitem->child and move to it */
+ newitem->child = newchild;
+ next = newchild;
+ }
+ child = child->next;
+ }
+ if (newitem && newitem->child)
+ {
+ newitem->child->prev = newchild;
+ }
+
+ return newitem;
+
+fail:
+ if (newitem != NULL)
+ {
+ cJSON_Delete(newitem);
+ }
+
+ return NULL;
+}
+
+static void skip_oneline_comment(char **input)
+{
+ *input += static_strlen("//");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if ((*input)[0] == '\n') {
+ *input += static_strlen("\n");
+ return;
+ }
+ }
+}
+
+static void skip_multiline_comment(char **input)
+{
+ *input += static_strlen("/*");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
+ {
+ *input += static_strlen("*/");
+ return;
+ }
+ }
+}
+
+static void minify_string(char **input, char **output) {
+ (*output)[0] = (*input)[0];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+
+
+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
+ (*output)[0] = (*input)[0];
+
+ if ((*input)[0] == '\"') {
+ (*output)[0] = '\"';
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ return;
+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
+ (*output)[1] = (*input)[1];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ }
+ }
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+ char *into = json;
+
+ if (json == NULL)
+ {
+ return;
+ }
+
+ while (json[0] != '\0')
+ {
+ switch (json[0])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ json++;
+ break;
+
+ case '/':
+ if (json[1] == '/')
+ {
+ skip_oneline_comment(&json);
+ }
+ else if (json[1] == '*')
+ {
+ skip_multiline_comment(&json);
+ } else {
+ json++;
+ }
+ break;
+
+ case '\"':
+ minify_string(&json, (char**)&into);
+ break;
+
+ default:
+ into[0] = json[0];
+ json++;
+ into++;
+ }
+ }
+
+ /* and null-terminate. */
+ *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xff) == cJSON_True;
+}
+
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
+{
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
+ {
+ return false;
+ }
+
+ /* check if type is valid */
+ switch (a->type & 0xFF)
+ {
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ case cJSON_Number:
+ case cJSON_String:
+ case cJSON_Raw:
+ case cJSON_Array:
+ case cJSON_Object:
+ break;
+
+ default:
+ return false;
+ }
+
+ /* identical objects are equal */
+ if (a == b)
+ {
+ return true;
+ }
+
+ switch (a->type & 0xFF)
+ {
+ /* in these cases and equal type is enough */
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ return true;
+
+ case cJSON_Number:
+ if (compare_double(a->valuedouble, b->valuedouble))
+ {
+ return true;
+ }
+ return false;
+
+ case cJSON_String:
+ case cJSON_Raw:
+ if ((a->valuestring == NULL) || (b->valuestring == NULL))
+ {
+ return false;
+ }
+ if (strcmp(a->valuestring, b->valuestring) == 0)
+ {
+ return true;
+ }
+
+ return false;
+
+ case cJSON_Array:
+ {
+ cJSON *a_element = a->child;
+ cJSON *b_element = b->child;
+
+ for (; (a_element != NULL) && (b_element != NULL);)
+ {
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
+ {
+ return false;
+ }
+
+ a_element = a_element->next;
+ b_element = b_element->next;
+ }
+
+ /* one of the arrays is longer than the other */
+ if (a_element != b_element) {
+ return false;
+ }
+
+ return true;
+ }
+
+ case cJSON_Object:
+ {
+ cJSON *a_element = NULL;
+ cJSON *b_element = NULL;
+ cJSON_ArrayForEach(a_element, a)
+ {
+ /* TODO This has O(n^2) runtime, which is horrible! */
+ b_element = get_object_item(b, a_element->string, case_sensitive);
+ if (b_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
+ * TODO: Do this the proper way, this is just a fix for now */
+ cJSON_ArrayForEach(b_element, b)
+ {
+ a_element = get_object_item(a, b_element->string, case_sensitive);
+ if (a_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+ return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+ global_hooks.deallocate(object);
+}
diff --git a/src/cdrom/CMakeLists.txt b/src/cdrom/CMakeLists.txt
index 201cee7f6d..d3b38095e7 100644
--- a/src/cdrom/CMakeLists.txt
+++ b/src/cdrom/CMakeLists.txt
@@ -13,4 +13,4 @@
# Copyright 2020-2021 David Hrdlička.
#
-add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_mitsumi.c)
+add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_ioctl.c cdrom_mitsumi.c)
diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c
index 8970837082..88811c0168 100644
--- a/src/cdrom/cdrom.c
+++ b/src/cdrom/cdrom.c
@@ -442,7 +442,7 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len)
{
int ret = 1;
- if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING)) {
+ if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING) || dev->audio_muted_soft) {
cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id);
if (dev->cd_status == CD_STATUS_PLAYING)
dev->seek_pos += (len >> 11);
@@ -557,6 +557,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
len += pos;
}
+ dev->audio_muted_soft = 0;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
@@ -578,6 +579,7 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit)
int m = 0;
int s = 0;
int f = 0;
+ uint32_t pos2 = 0;
if (dev->cd_status == CD_STATUS_DATA_ONLY)
return 0;
@@ -614,14 +616,21 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit)
break;
}
+ pos2 = pos - 1;
+ if (pos2 == 0xffffffff)
+ pos2 = pos + 1;
+
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
- if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
- cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
- cdrom_stop(dev);
- return 0;
- }
+ if (!(dev->ops->track_type(dev, pos2) & CD_TRACK_AUDIO)) {
+ cdrom_log("CD-ROM %i: Track Search: LBA %08X not on an audio track\n", dev->id, pos);
+ dev->audio_muted_soft = 1;
+ if (dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)
+ dev->audio_muted_soft = 0;
+ } else
+ dev->audio_muted_soft = 0;
+ cdrom_log("Track Search Toshiba: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos);
dev->cd_buflen = 0;
dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED;
return 1;
@@ -647,6 +656,7 @@ cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit)
dev->seek_pos = pos;
+ dev->audio_muted_soft = 0;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
@@ -676,6 +686,7 @@ cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos)
pos = MSFtoLBA(m, s, f) - 150;
dev->cd_end = pos;
+ dev->audio_muted_soft = 0;
dev->cd_buflen = 0;
dev->cd_status = CD_STATUS_PLAYING;
return 1;
@@ -717,16 +728,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type)
break;
}
- cdrom_log("Toshiba/NEC Play Audio: MSF = %06x, type = %02x, cdstatus = %02x\n", pos, type, dev->cd_status);
-
- /* Do this at this point, since it's at this point that we know the
- actual LBA position to start playing from. */
- if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
- cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
- cdrom_stop(dev);
- return 0;
- }
-
+ cdrom_log("Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos);
dev->cd_buflen = 0;
dev->cd_status = CD_STATUS_PLAYING;
return 1;
@@ -770,6 +772,7 @@ cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type)
break;
}
+ dev->audio_muted_soft = 0;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
@@ -1007,6 +1010,11 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
else
ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op;
+ /*If a valid audio track is detected with audio on, unmute it.*/
+ if (dev->ops->track_type(dev, dev->seek_pos) & CD_TRACK_AUDIO)
+ dev->audio_muted_soft = 0;
+
+ cdrom_log("SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d.\n", dev->seek_pos, dev->cd_end, dev->audio_muted_soft);
b[0] = subc.attr;
b[1] = bin2bcd(subc.track);
b[2] = bin2bcd(subc.index);
@@ -1516,8 +1524,9 @@ static void
read_sector_to_buffer(cdrom_t *dev, uint8_t *rbuf, uint32_t msf, uint32_t lba, int mode2, int len)
{
uint8_t *bb = rbuf;
+ const int offset = (!!(mode2 & 0x03)) ? 24 : 16;
- dev->ops->read_sector(dev, CD_READ_DATA, rbuf + 16, lba);
+ dev->ops->read_sector(dev, CD_READ_DATA, rbuf + offset, lba);
/* Sync bytes */
bb[0] = 0;
@@ -1952,7 +1961,7 @@ cdrom_hard_reset(void)
dev->cd_status = CD_STATUS_EMPTY;
- if (dev->host_drive == 200) {
+ if (strlen(dev->image_path) > 0) {
#ifdef _WIN32
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
dev->image_path[strlen(dev->image_path) - 1] = '\\';
@@ -1962,7 +1971,10 @@ cdrom_hard_reset(void)
dev->image_path[strlen(dev->image_path) - 1] = '/';
#endif
- cdrom_image_open(dev, dev->image_path);
+ if ((strlen(dev->image_path) != 0) && (strstr(dev->image_path, "ioctl://") == dev->image_path))
+ cdrom_ioctl_open(dev, dev->image_path);
+ else
+ cdrom_image_open(dev, dev->image_path);
}
}
}
@@ -2011,16 +2023,12 @@ cdrom_eject(uint8_t id)
cdrom_t *dev = &cdrom[id];
/* This entire block should be in cdrom.c/cdrom_eject(dev*) ... */
- if (dev->host_drive == 0) {
+ if (strlen(dev->image_path) == 0) {
/* Switch from empty to empty. Do nothing. */
return;
}
- if (dev->host_drive == 200)
- strcpy(dev->prev_image_path, dev->image_path);
-
- dev->prev_host_drive = dev->host_drive;
- dev->host_drive = 0;
+ strcpy(dev->prev_image_path, dev->image_path);
dev->ops->exit(dev);
dev->ops = NULL;
@@ -2039,7 +2047,7 @@ cdrom_reload(uint8_t id)
{
cdrom_t *dev = &cdrom[id];
- if ((dev->host_drive == dev->prev_host_drive) || (dev->prev_host_drive == 0) || (dev->host_drive != 0)) {
+ if ((strcmp(dev->image_path, dev->prev_image_path) == 0) || (strlen(dev->prev_image_path) == 0) || (strlen(dev->image_path) > 0)) {
/* Switch from empty to empty. Do nothing. */
return;
}
@@ -2049,26 +2057,29 @@ cdrom_reload(uint8_t id)
dev->ops = NULL;
memset(dev->image_path, 0, sizeof(dev->image_path));
- if (dev->prev_host_drive == 200) {
+ if (strlen(dev->image_path) > 0) {
/* Reload a previous image. */
- strcpy(dev->image_path, dev->prev_image_path);
+ if (strlen(dev->prev_image_path) > 0)
+ strcpy(dev->image_path, dev->prev_image_path);
#ifdef _WIN32
- if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
- dev->image_path[strlen(dev->image_path) - 1] = '\\';
+ if (strlen(dev->prev_image_path) > 0) {
+ if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
+ dev->image_path[strlen(dev->image_path) - 1] = '\\';
+ }
#else
- if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\'))
- dev->image_path[strlen(dev->image_path) - 1] = '/';
+ if (strlen(dev->prev_image_path) > 0) {
+ if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\'))
+ dev->image_path[strlen(dev->image_path) - 1] = '/';
+ }
#endif
- cdrom_image_open(dev, dev->image_path);
+ if ((strlen(dev->image_path) != 0) && (strstr(dev->image_path, "ioctl://") == dev->image_path))
+ cdrom_ioctl_open(dev, dev->image_path);
+ else
+ cdrom_image_open(dev, dev->image_path);
cdrom_insert(id);
-
- if (strlen(dev->image_path) == 0)
- dev->host_drive = 0;
- else
- dev->host_drive = 200;
}
plat_cdrom_ui_update(id, 1);
diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c
index 0c7ee03a02..2203674cdb 100644
--- a/src/cdrom/cdrom_image.c
+++ b/src/cdrom/cdrom_image.c
@@ -97,6 +97,9 @@ image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc)
subc->rel_m = rel_pos.min;
subc->rel_s = rel_pos.sec;
subc->rel_f = rel_pos.fr;
+
+ cdrom_image_log("image_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n",
+ subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f, subc->rel_m, subc->rel_s, subc->rel_f);
}
static int
@@ -217,6 +220,12 @@ image_track_type(cdrom_t *dev, uint32_t lba)
return 0;
}
+static int
+image_ext_medium_changed(cdrom_t *dev)
+{
+ return 0;
+}
+
static void
image_exit(cdrom_t *dev)
{
@@ -241,6 +250,7 @@ static const cdrom_ops_t cdrom_image_ops = {
image_sector_size,
image_read_sector,
image_track_type,
+ image_ext_medium_changed,
image_exit
};
@@ -249,7 +259,6 @@ image_open_abort(cdrom_t *dev)
{
cdrom_image_close(dev);
dev->ops = NULL;
- dev->host_drive = 0;
dev->image_path[0] = 0;
return 1;
}
diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c
index 151ddfe9f0..fdfa4a4abc 100644
--- a/src/cdrom/cdrom_image_backend.c
+++ b/src/cdrom/cdrom_image_backend.c
@@ -70,12 +70,12 @@ cdrom_image_backend_log(const char *fmt, ...)
static int
bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
{
- track_file_t *tf = (track_file_t *) priv;
+ track_file_t *tf;
cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n",
tf->fp, seek, count);
- if (tf->fp == NULL)
+ if ((tf = (track_file_t *) priv)->fp == NULL)
return 0;
if (fseeko64(tf->fp, seek, SEEK_SET) == -1) {
@@ -98,16 +98,15 @@ bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
static uint64_t
bin_get_length(void *priv)
{
- off64_t len;
- track_file_t *tf = (track_file_t *) priv;
+ track_file_t *tf;
cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->fp);
- if (tf->fp == NULL)
+ if ((tf = (track_file_t *) priv)->fp == NULL)
return 0;
fseeko64(tf->fp, 0, SEEK_END);
- len = ftello64(tf->fp);
+ const off64_t len = ftello64(tf->fp);
cdrom_image_backend_log("CDROM: binary_length(%08lx) = %" PRIu64 "\n", tf->fp, len);
return len;
@@ -248,26 +247,20 @@ cdi_set_device(cd_img_t *cdi, const char *path)
return 0;
}
-/* TODO: This never returns anything other than 1, should it even be an int? */
-int
+void
cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out)
{
*st_track = 1;
*end = cdi->tracks_num - 1;
FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr);
-
- return 1;
}
-/* TODO: This never returns anything other than 1, should it even be an int? */
-int
+void
cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out)
{
*st_track = 1;
*end = cdi->tracks_num - 1;
*lead_out = cdi->tracks[*end].start;
-
- return 1;
}
int
@@ -286,12 +279,11 @@ int
cdi_get_audio_track_info(cd_img_t *cdi, UNUSED(int end), int track, int *track_num, TMSF *start, uint8_t *attr)
{
const track_t *trk = &cdi->tracks[track - 1];
- int pos = trk->start + 150;
if ((track < 1) || (track > cdi->tracks_num))
return 0;
- pos = trk->start + 150;
+ const int pos = trk->start + 150;
FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr);
@@ -320,9 +312,6 @@ cdi_get_audio_track_info_lba(cd_img_t *cdi, UNUSED(int end), int track, int *tra
int
cdi_get_track(cd_img_t *cdi, uint32_t sector)
{
- const track_t *cur;
- const track_t *next;
-
/* There must be at least two tracks - data and lead out. */
if (cdi->tracks_num < 2)
return -1;
@@ -330,8 +319,8 @@ cdi_get_track(cd_img_t *cdi, uint32_t sector)
/* This has a problem - the code skips the last track, which is
lead out - is that correct? */
for (int i = 0; i < (cdi->tracks_num - 1); i++) {
- cur = &cdi->tracks[i];
- next = &cdi->tracks[i + 1];
+ const track_t *cur = &cdi->tracks[i];
+ const track_t *next = &cdi->tracks[i + 1];
/* Take into account cue sheets that do not start on sector 0. */
if ((i == 0) && (sector < cur->start))
@@ -348,16 +337,15 @@ cdi_get_track(cd_img_t *cdi, uint32_t sector)
int
cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos)
{
- int cur_track = cdi_get_track(cdi, sector);
- const track_t *trk;
+ const int cur_track = cdi_get_track(cdi, sector);
if (cur_track < 1)
return 0;
- *track = (uint8_t) cur_track;
- trk = &cdi->tracks[*track - 1];
- *attr = trk->attr;
- *index = 1;
+ *track = (uint8_t) cur_track;
+ const track_t *trk = &cdi->tracks[*track - 1];
+ *attr = trk->attr;
+ *index = 1;
FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr);
@@ -370,16 +358,11 @@ cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track,
int
cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
{
- size_t length;
- int track = cdi_get_track(cdi, sector) - 1;
- uint64_t sect = (uint64_t) sector;
- uint64_t seek;
- track_t *trk;
- int track_is_raw;
- int ret;
+ const int track = cdi_get_track(cdi, sector) - 1;
+ const uint64_t sect = (uint64_t) sector;
int raw_size;
int cooked_size;
- uint64_t offset = 0ULL;
+ uint64_t offset;
int m = 0;
int s = 0;
int f = 0;
@@ -387,10 +370,10 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
if (track < 0)
return 0;
- trk = &cdi->tracks[track];
- track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448));
+ const track_t *trk = &cdi->tracks[track];
+ const int track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448));
- seek = trk->skip + ((sect - trk->start) * trk->sector_size);
+ const uint64_t seek = trk->skip + ((sect - trk->start) * trk->sector_size);
if (track_is_raw)
raw_size = trk->sector_size;
@@ -405,7 +388,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
} else
cooked_size = COOKED_SECTOR_SIZE;
- length = (raw ? raw_size : cooked_size);
+ const size_t length = (raw ? raw_size : cooked_size);
if (trk->mode2 && (trk->form >= 1))
offset = 24ULL;
@@ -414,7 +397,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
if (raw && !track_is_raw) {
memset(buffer, 0x00, 2448);
- ret = trk->file->read(trk->file, buffer + offset, seek, length);
+ const int ret = trk->file->read(trk->file, buffer + offset, seek, length);
if (!ret)
return 0;
/* Construct the rest of the raw sector. */
@@ -422,32 +405,28 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
buffer += 12;
FRAMES_TO_MSF(sector + 150, &m, &s, &f);
/* These have to be BCD. */
- buffer[12] = CDROM_BCD(m & 0xff);
- buffer[13] = CDROM_BCD(s & 0xff);
- buffer[14] = CDROM_BCD(f & 0xff);
+ buffer[0] = CDROM_BCD(m & 0xff);
+ buffer[1] = CDROM_BCD(s & 0xff);
+ buffer[2] = CDROM_BCD(f & 0xff);
/* Data, should reflect the actual sector type. */
- buffer[15] = trk->mode2 ? 2 : 1;
+ buffer[3] = trk->mode2 ? 2 : 1;
return 1;
} else if (!raw && track_is_raw)
return trk->file->read(trk->file, buffer, seek + offset, length);
- else {
+ else
return trk->file->read(trk->file, buffer, seek, length);
- }
}
int
cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num)
{
- int sector_size;
int success = 1;
- uint8_t *buf;
- uint32_t buf_len;
/* TODO: This fails to account for Mode 2. Shouldn't we have a function
to get sector size? */
- sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
- buf_len = num * sector_size;
- buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t));
+ const int sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
+ const uint32_t buf_len = num * sector_size;
+ uint8_t *buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t));
for (uint32_t i = 0; i < num; i++) {
success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i);
@@ -455,7 +434,9 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3
break;
/* Based on the DOSBox patch, but check all 8 bytes and makes sure it's not an
audio track. */
- if (raw && sector < cdi->tracks[0].length && !cdi->tracks[0].mode2 && (cdi->tracks[0].attr != AUDIO_TRACK) && *(uint64_t *) &(buf[i * sector_size + 2068]))
+ if (raw && (sector < cdi->tracks[0].length) &&
+ !cdi->tracks[0].mode2 && (cdi->tracks[0].attr != AUDIO_TRACK) &&
+ *(uint64_t *) &(buf[(i * sector_size) + 2068]))
return 0;
}
@@ -470,16 +451,13 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3
int
cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector)
{
- int track = cdi_get_track(cdi, sector) - 1;
- track_t *trk;
- uint64_t s = (uint64_t) sector;
- uint64_t seek;
+ const int track = cdi_get_track(cdi, sector) - 1;
if (track < 0)
return 0;
- trk = &cdi->tracks[track];
- seek = trk->skip + ((s - trk->start) * trk->sector_size);
+ const track_t *trk = &cdi->tracks[track];
+ const uint64_t seek = trk->skip + (((uint64_t) sector - trk->start) * trk->sector_size);
if (trk->sector_size != 2448)
return 0;
@@ -489,26 +467,24 @@ cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector)
int
cdi_get_sector_size(cd_img_t *cdi, uint32_t sector)
{
- int track = cdi_get_track(cdi, sector) - 1;
- const track_t *trk;
+ const int track = cdi_get_track(cdi, sector) - 1;
if (track < 0)
return 0;
- trk = &cdi->tracks[track];
+ const track_t *trk = &cdi->tracks[track];
return trk->sector_size;
}
int
cdi_is_mode2(cd_img_t *cdi, uint32_t sector)
{
- int track = cdi_get_track(cdi, sector) - 1;
- const track_t *trk;
+ const int track = cdi_get_track(cdi, sector) - 1;
if (track < 0)
return 0;
- trk = &cdi->tracks[track];
+ const track_t *trk = &cdi->tracks[track];
return !!(trk->mode2);
}
@@ -516,13 +492,12 @@ cdi_is_mode2(cd_img_t *cdi, uint32_t sector)
int
cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector)
{
- int track = cdi_get_track(cdi, sector) - 1;
- const track_t *trk;
+ const int track = cdi_get_track(cdi, sector) - 1;
if (track < 0)
return 0;
- trk = &cdi->tracks[track];
+ const track_t *trk = &cdi->tracks[track];
return trk->form;
}
@@ -533,10 +508,12 @@ cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form)
uint8_t pvd[COOKED_SECTOR_SIZE];
uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */
- if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE))
- seek += 16;
- if (mode2 && (form >= 1))
- seek += 24;
+ if (sector_size == RAW_SECTOR_SIZE) {
+ if (!mode2 || (form == 0))
+ seek += 16;
+ else
+ seek += 24;
+ }
file->read(file, pvd, seek, COOKED_SECTOR_SIZE);
@@ -591,7 +568,7 @@ cdi_load_iso(cd_img_t *cdi, const char *filename)
/* Try to detect ISO type. */
trk.form = 0;
trk.mode2 = 0;
- /* TODO: Merge the first and last cases since they result in the same thing. */
+
if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0))
trk.sector_size = RAW_SECTOR_SIZE;
else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) {
@@ -601,9 +578,17 @@ cdi_load_iso(cd_img_t *cdi, const char *filename)
trk.sector_size = 2324;
trk.mode2 = 1;
trk.form = 2;
+ } else if (cdi_can_read_pvd(trk.file, 2328, 1, 2)) {
+ trk.sector_size = 2328;
+ trk.mode2 = 1;
+ trk.form = 2;
} else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) {
trk.sector_size = RAW_SECTOR_SIZE;
trk.mode2 = 1;
+ } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 1)) {
+ trk.sector_size = RAW_SECTOR_SIZE;
+ trk.mode2 = 1;
+ trk.form = 1;
} else {
/* We use 2048 mode 1 as the default. */
trk.sector_size = COOKED_SECTOR_SIZE;
@@ -711,9 +696,9 @@ static int
cdi_cue_get_frame(uint64_t *frames, char **line)
{
char temp[128];
- int min;
- int sec;
- int fr;
+ int min = 0;
+ int sec = 0;
+ int fr = 0;
int success;
success = cdi_cue_get_buffer(temp, line, 0);
@@ -754,17 +739,12 @@ static int
cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap)
{
/* Frames between index 0 (prestart) and 1 (current track start) must be skipped. */
- uint64_t skip;
- uint64_t temp;
track_t *prev = NULL;
/* Skip *MUST* be calculated even if prestart is 0. */
- if (prestart >= 0) {
- if (prestart > cur->start)
- return 0;
- skip = cur->start - prestart;
- } else
- skip = 0ULL;
+ if (prestart > cur->start)
+ return 0;
+ const uint64_t skip = cur->start - prestart;
if ((cdi->tracks != NULL) && (cdi->tracks_num != 0))
prev = &cdi->tracks[cdi->tracks_num - 1];
@@ -793,7 +773,7 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u
*total_pregap += cur_pregap;
cur->start += *total_pregap;
} else {
- temp = prev->file->get_length(prev->file) - (prev->skip);
+ const uint64_t temp = prev->file->get_length(prev->file) - (prev->skip);
prev->length = temp / ((uint64_t) prev->sector_size);
if ((temp % prev->sector_size) != 0)
prev->length++;
@@ -823,8 +803,6 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
{
track_t trk;
char pathname[MAX_FILENAME_LENGTH];
- char filename[MAX_FILENAME_LENGTH];
- char temp[MAX_FILENAME_LENGTH];
uint64_t shift = 0ULL;
uint64_t prestart = 0ULL;
uint64_t cur_pregap = 0ULL;
@@ -836,7 +814,6 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
int can_add_track = 0;
FILE *fp;
char buf[MAX_LINE_LENGTH];
- char ansi[MAX_FILENAME_LENGTH];
char *line;
char *command;
char *type;
@@ -877,7 +854,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
}
}
- success = cdi_cue_get_keyword(&command, &line);
+ (void) cdi_cue_get_keyword(&command, &line);
if (!strcmp(command, "TRACK")) {
if (can_add_track)
@@ -980,6 +957,9 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
break;
}
} else if (!strcmp(command, "FILE")) {
+ char filename[MAX_FILENAME_LENGTH];
+ char ansi[MAX_FILENAME_LENGTH];
+
if (can_add_track)
success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap);
else
@@ -1002,7 +982,6 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
error = 1;
if (!strcmp(type, "BINARY")) {
- memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(char));
path_append_filename(filename, pathname, ansi);
trk.file = track_file_init(filename, &error);
}
diff --git a/src/cdrom/cdrom_ioctl.c b/src/cdrom/cdrom_ioctl.c
new file mode 100644
index 0000000000..a204fad0f4
--- /dev/null
+++ b/src/cdrom/cdrom_ioctl.c
@@ -0,0 +1,278 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * CD-ROM passthrough support.
+ *
+ *
+ *
+ * Authors: TheCollector1995, ,
+ * Miran Grca,
+ *
+ * Copyright 2023 TheCollector1995.
+ * Copyright 2023 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/config.h>
+#include <86box/path.h>
+#include <86box/plat.h>
+#include <86box/plat_cdrom.h>
+#include <86box/scsi_device.h>
+#include <86box/cdrom.h>
+
+#ifdef ENABLE_CDROM_IOCTL_LOG
+int cdrom_ioctl_do_log = ENABLE_CDROM_IOCTL_LOG;
+
+void
+cdrom_ioctl_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (cdrom_ioctl_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define cdrom_ioctl_log(fmt, ...)
+#endif
+
+/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
+ there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
+ of the audio while audio still plays. With an absolute conversion, the counter is fine. */
+#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
+
+static void
+ioctl_get_tracks(UNUSED(cdrom_t *dev), int *first, int *last)
+{
+ TMSF tmsf;
+
+ plat_cdrom_get_audio_tracks(first, last, &tmsf);
+}
+
+static void
+ioctl_get_track_info(UNUSED(cdrom_t *dev), uint32_t track, int end, track_info_t *ti)
+{
+ TMSF tmsf;
+
+ plat_cdrom_get_audio_track_info(end, track, &ti->number, &tmsf, &ti->attr);
+
+ ti->m = tmsf.min;
+ ti->s = tmsf.sec;
+ ti->f = tmsf.fr;
+}
+
+static void
+ioctl_get_subchannel(UNUSED(cdrom_t *dev), uint32_t lba, subchannel_t *subc)
+{
+ TMSF rel_pos;
+ TMSF abs_pos;
+
+ if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED)) {
+ const uint32_t trk = plat_cdrom_get_track_start(lba, &subc->attr, &subc->track);
+
+ FRAMES_TO_MSF(lba + 150, &abs_pos.min, &abs_pos.sec, &abs_pos.fr);
+
+ /* Absolute position should be adjusted by 150, not the relative ones. */
+ FRAMES_TO_MSF(lba - trk, &rel_pos.min, &rel_pos.sec, &rel_pos.fr);
+
+ subc->index = 1;
+ } else
+ plat_cdrom_get_audio_sub(lba, &subc->attr, &subc->track, &subc->index,
+ &rel_pos, &abs_pos);
+
+ subc->abs_m = abs_pos.min;
+ subc->abs_s = abs_pos.sec;
+ subc->abs_f = abs_pos.fr;
+
+ subc->rel_m = rel_pos.min;
+ subc->rel_s = rel_pos.sec;
+ subc->rel_f = rel_pos.fr;
+
+ cdrom_ioctl_log("ioctl_get_subchannel(): %02X, %02X, %02i, %02i:%02i:%02i, %02i:%02i:%02i\n",
+ subc->attr, subc->track, subc->index, subc->abs_m, subc->abs_s, subc->abs_f, subc->rel_m, subc->rel_s, subc->rel_f);
+}
+
+static int
+ioctl_get_capacity(UNUSED(cdrom_t *dev))
+{
+ int ret;
+
+ ret = plat_cdrom_get_last_block();
+ cdrom_ioctl_log("GetCapacity=%x.\n", ret);
+ return ret;
+}
+
+static int
+ioctl_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
+{
+ int m;
+ int s;
+ int f;
+
+ if (dev->cd_status == CD_STATUS_DATA_ONLY)
+ return 0;
+
+ if (ismsf) {
+ m = (pos >> 16) & 0xff;
+ s = (pos >> 8) & 0xff;
+ f = pos & 0xff;
+ pos = MSFtoLBA(m, s, f) - 150;
+ }
+
+ /* GetTrack requires LBA. */
+ return plat_cdrom_is_track_audio(pos);
+}
+
+static int
+ioctl_is_track_pre(UNUSED(cdrom_t *dev), uint32_t lba)
+{
+ return plat_cdrom_is_track_pre(lba);
+}
+
+static int
+ioctl_sector_size(UNUSED(cdrom_t *dev), uint32_t lba)
+{
+ cdrom_ioctl_log("LBA=%x.\n", lba);
+ return plat_cdrom_get_sector_size(lba);
+}
+
+static int
+ioctl_read_sector(UNUSED(cdrom_t *dev), int type, uint8_t *b, uint32_t lba)
+{
+ switch (type) {
+ case CD_READ_DATA:
+ cdrom_ioctl_log("cdrom_ioctl_read_sector(): Data.\n");
+ return plat_cdrom_read_sector(b, 0, lba);
+ case CD_READ_AUDIO:
+ cdrom_ioctl_log("cdrom_ioctl_read_sector(): Audio.\n");
+ return plat_cdrom_read_sector(b, 1, lba);
+ case CD_READ_RAW:
+ cdrom_ioctl_log("cdrom_ioctl_read_sector(): Raw.\n");
+ return plat_cdrom_read_sector(b, 1, lba);
+ default:
+ cdrom_ioctl_log("cdrom_ioctl_read_sector(): Unknown CD read type.\n");
+ break;
+ }
+ return 0;
+}
+
+static int
+ioctl_track_type(cdrom_t *dev, uint32_t lba)
+{
+ int ret = 0;
+
+ if (ioctl_is_track_audio(dev, lba, 0))
+ ret = CD_TRACK_AUDIO;
+
+ cdrom_ioctl_log("cdrom_ioctl_track_type(): %i\n", ret);
+
+ return ret;
+}
+
+static int
+ioctl_ext_medium_changed(cdrom_t *dev)
+{
+ int ret;
+
+ if ((dev->cd_status == CD_STATUS_PLAYING) || (dev->cd_status == CD_STATUS_PAUSED))
+ ret = 0;
+ else
+ ret = plat_cdrom_ext_medium_changed();
+
+ if (ret == 1) {
+ dev->cd_status = CD_STATUS_STOPPED;
+ dev->cdrom_capacity = ioctl_get_capacity(dev);
+ } else if (ret == -1)
+ dev->cd_status = CD_STATUS_EMPTY;
+
+ return ret;
+}
+
+static void
+ioctl_exit(cdrom_t *dev)
+{
+ cdrom_ioctl_log("CDROM: ioctl_exit(%s)\n", dev->image_path);
+ dev->cd_status = CD_STATUS_EMPTY;
+
+ plat_cdrom_close();
+
+ dev->ops = NULL;
+}
+
+static const cdrom_ops_t cdrom_ioctl_ops = {
+ ioctl_get_tracks,
+ ioctl_get_track_info,
+ ioctl_get_subchannel,
+ ioctl_is_track_pre,
+ ioctl_sector_size,
+ ioctl_read_sector,
+ ioctl_track_type,
+ ioctl_ext_medium_changed,
+ ioctl_exit
+};
+
+static int
+cdrom_ioctl_open_abort(cdrom_t *dev)
+{
+ cdrom_ioctl_close(dev);
+ dev->ops = NULL;
+ dev->image_path[0] = 0;
+ return 1;
+}
+
+int
+cdrom_ioctl_open(cdrom_t *dev, const char *drv)
+{
+ const char *actual_drv = &(drv[8]);
+
+ /* Make sure to not STRCPY if the two are pointing
+ at the same place. */
+ if (drv != dev->image_path)
+ strcpy(dev->image_path, drv);
+
+ /* Open the image. */
+ if (strstr(drv, "ioctl://") != drv)
+ return cdrom_ioctl_open_abort(dev);
+ cdrom_ioctl_log("actual_drv = %s\n", actual_drv);
+ int i = plat_cdrom_set_drive(actual_drv);
+ if (!i)
+ return cdrom_ioctl_open_abort(dev);
+
+ /* All good, reset state. */
+ dev->cd_status = CD_STATUS_STOPPED;
+ dev->is_dir = 0;
+ dev->seek_pos = 0;
+ dev->cd_buflen = 0;
+ dev->cdrom_capacity = ioctl_get_capacity(dev);
+ cdrom_ioctl_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n",
+ dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL);
+
+ /* Attach this handler to the drive. */
+ dev->ops = &cdrom_ioctl_ops;
+
+ return 0;
+}
+
+void
+cdrom_ioctl_close(cdrom_t *dev)
+{
+ cdrom_ioctl_log("CDROM: ioctl_close(%s)\n", dev->image_path);
+
+ if (dev && dev->ops && dev->ops->exit)
+ dev->ops->exit(dev);
+}
+
diff --git a/src/cdrom/cdrom_mitsumi.c b/src/cdrom/cdrom_mitsumi.c
index 7f4d2645ba..01a9cf0471 100644
--- a/src/cdrom/cdrom_mitsumi.c
+++ b/src/cdrom/cdrom_mitsumi.c
@@ -147,14 +147,18 @@ mitsumi_cdrom_log(const char *fmt, ...)
# define mitsumi_cdrom_log(fmt, ...)
#endif
+static int
+mitsumi_cdrom_is_ready(const cdrom_t *dev)
+{
+ return (dev->image_path[0] != 0x00);
+}
+
static void
mitsumi_cdrom_reset(mcd_t *dev)
{
cdrom_t cdrom;
- cdrom.host_drive = 0;
-
- dev->stat = cdrom.host_drive ? (STAT_READY | STAT_CHANGE) : 0;
+ dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | STAT_CHANGE) : 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 0;
dev->buf_count = 0;
@@ -344,18 +348,18 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
}
if (!dev->cmdrd_count)
- dev->stat = cdrom.host_drive ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
+ dev->stat = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
return;
}
dev->cmd = val;
dev->cmdbuf_idx = 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 1;
- dev->cmdbuf[0] = cdrom.host_drive ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
+ dev->cmdbuf[0] = mitsumi_cdrom_is_ready(&cdrom) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->data = 0;
switch (val) {
case CMD_GET_INFO:
- if (cdrom.host_drive) {
+ if (mitsumi_cdrom_is_ready(&cdrom)) {
cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1]));
dev->cmdbuf_count = 10;
dev->readcount = 0;
@@ -365,7 +369,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
}
break;
case CMD_GET_Q:
- if (cdrom.host_drive) {
+ if (mitsumi_cdrom_is_ready(&cdrom)) {
cdrom_get_q(&cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC);
dev->cmdbuf_count = 11;
dev->readcount = 0;
@@ -391,7 +395,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_READ1X:
case CMD_READ2X:
- if (cdrom.host_drive) {
+ if (mitsumi_cdrom_is_ready(&cdrom)) {
dev->readcount = 0;
dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ;
dev->cmdrd_count = 6;
diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt
index 0f3c78c846..4daccd2d8e 100644
--- a/src/chipset/CMakeLists.txt
+++ b/src/chipset/CMakeLists.txt
@@ -14,13 +14,15 @@
#
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c
- ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c ims8848.c intel_82335.c
+ ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c ali1409.c headland.c ims8848.c intel_82335.c
compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c
intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c
opti602.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c
- sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c
- sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c
- umc_hb4.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c)
+ sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5581.c sis_5591.c sis_5600.c
+ sis_5511_h2p.c sis_5571_h2p.c sis_5581_h2p.c sis_5591_h2p.c sis_5600_h2p.c
+ sis_5513_p2i.c sis_5513_ide.c sis_5572_usb.c sis_5595_pmu.c sis_55xx.c via_vt82c49x.c
+ via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c
+ umc_8886.c umc_hb4.c umc_8890.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c)
if(OLIVETTI)
target_sources(chipset PRIVATE olivetti_eva.c)
diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c
new file mode 100644
index 0000000000..3e4286f808
--- /dev/null
+++ b/src/chipset/ali1409.c
@@ -0,0 +1,199 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the ALi M1409 chipset.
+ *
+ * Note: This chipset has no datasheet, everything were done via
+ * reverse engineering.
+ *
+ *
+ *
+ * Authors: Jose Phillips,
+ * Sarah Walker,
+ *
+ * Copyright 2024 Jose Phillips.
+ * Copyright 2008-2018 Sarah Walker.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include "cpu.h"
+#include <86box/timer.h>
+#include <86box/io.h>
+#include <86box/device.h>
+
+#include <86box/apm.h>
+#include <86box/mem.h>
+#include <86box/fdd.h>
+#include <86box/fdc.h>
+#include <86box/smram.h>
+#include <86box/chipset.h>
+
+
+
+#ifdef ENABLE_ALI1409_LOG
+int ali1409_do_log = ENABLE_ALI1409_LOG;
+
+static void
+ali1409_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (ali1409_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define ali1409_log(fmt, ...)
+#endif
+
+typedef struct ali_1409_t {
+ uint8_t is_g;
+ uint8_t index;
+ uint8_t cfg_locked;
+ uint8_t reg_57h;
+ uint8_t regs[256];
+ uint8_t last_reg;
+} ali1409_t;
+
+
+static void
+ali1409_write(uint16_t addr, uint8_t val, void *priv)
+{
+ ali1409_t *dev = (ali1409_t *) priv;
+ ali1409_log ("INPUT:addr %02x ,Value %02x \n" , addr , val);
+
+ if (addr & 1) {
+ if (dev->cfg_locked) {
+ if (dev->last_reg == 0x14 && val == 0x09)
+ dev->cfg_locked = 0;
+
+ dev->last_reg = val;
+ return;
+ }
+
+ if (dev->index == 0xff && val == 0xff)
+ dev->cfg_locked = 1;
+ else {
+ ali1409_log("Write reg %02x %02x %08x\n", dev->index, val, cs);
+ dev->regs[dev->index] = val;
+
+ switch (dev->index) {
+ case 0xa:
+ switch ((val >> 4) & 3) {
+ case 0:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 1:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
+ break;
+ case 2:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ break;
+ case 0xb:
+ switch ((val >> 4) & 3) {
+ case 0:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ break;
+ case 1:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
+ break;
+ case 2:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY| MEM_WRITE_INTERNAL);
+ break;
+ case 3:
+ mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ break;
+ }
+ break;
+ }
+ }
+ } else
+ dev->index = val;
+}
+
+
+static uint8_t
+ali1409_read(uint16_t addr, void *priv)
+{
+ ali1409_log ("reading at %02X\n",addr);
+ const ali1409_t *dev = (ali1409_t *) priv;
+ uint8_t ret = 0xff;
+
+ if (dev->cfg_locked)
+ ret = 0xff;
+ if (addr & 1) {
+ if ((dev->index >= 0xc0 || dev->index == 0x20) && cpu_iscyrix)
+ ret = 0xff;
+ ret = dev->regs[dev->index];
+ } else
+ ret = dev->index;
+ return ret;
+}
+
+
+
+static void
+ali1409_close(void *priv)
+{
+ ali1409_t *dev = (ali1409_t *) priv;
+
+ free(dev);
+}
+
+static void *
+ali1409_init(const device_t *info)
+{
+ ali1409_t *dev = (ali1409_t *) malloc(sizeof(ali1409_t));
+ memset(dev, 0, sizeof(ali1409_t));
+
+ dev->cfg_locked = 1;
+
+ /* M1409 Ports:
+ 22h Index Port
+ 23h Data Port
+ */
+
+ ali1409_log ("Bus speed: %i",cpu_busspeed);
+
+
+ io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
+ io_sethandler(0x037f, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
+ io_sethandler(0x03f3, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
+
+ return dev;
+}
+
+const device_t ali1409_device = {
+ .name = "ALi M1409",
+ .internal_name = "ali1409",
+ .flags = 0,
+ .local = 0,
+ .init = ali1409_init,
+ .close = ali1409_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c
index fe3a0fda31..f35ec7590e 100644
--- a/src/chipset/ali1543.c
+++ b/src/chipset/ali1543.c
@@ -197,6 +197,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */
dev->pci_conf[addr] = val & 0xdf;
soft_reset_pci = !!(val & 0x80);
+ pci_set_mirq_level(PCI_MIRQ0, !(val & 0x10));
pci_set_mirq_level(PCI_MIRQ2, !(val & 0x10));
ali1543_log("INTAJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]);
pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[val & 0x0f]);
@@ -412,11 +413,13 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
case 0x74: /* USB IRQ Routing - we cheat and use MIRQ4 */
dev->pci_conf[addr] = val & 0xdf;
/* TODO: MIRQ level/edge control - if bit 4 = 1, it's level */
+ pci_set_mirq_level(PCI_MIRQ4, !(val & 0x10));
pci_set_mirq_routing(PCI_MIRQ4, ali1533_irq_routing[val & 0x0f]);
break;
case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */
dev->pci_conf[addr] = val & 0x1f;
+ pci_set_mirq_level(PCI_MIRQ1, !(val & 0x10));
pci_set_mirq_level(PCI_MIRQ3, !(val & 0x10));
ali1543_log("INTBJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]);
pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]);
@@ -704,7 +707,7 @@ ali5229_chip_reset(ali1543_t *dev)
ali5229_write(0, 0x09, 0xfa, dev);
ali5229_write(0, 0x52, 0x00, dev);
- ali5229_write(0, 0x50, 0x00, dev);
+ ali5229_write(0, 0x50, 0x02, dev);
sff_set_slot(dev->ide_controller[0], dev->ide_slot);
sff_set_slot(dev->ide_controller[1], dev->ide_slot);
@@ -717,7 +720,7 @@ static void
ali5229_write(int func, int addr, uint8_t val, void *priv)
{
ali1543_t *dev = (ali1543_t *) priv;
- ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val);
+ ali1543_log("M5229: [W] dev->ide_conf[%02x] = %02x\n", addr, val);
if (func > 0)
return;
@@ -756,6 +759,10 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
ali5229_ide_irq_handler(dev);
break;
+ case 0x0d: /* LT - Latency Timer */
+ dev->ide_conf[addr] = val;
+ break;
+
/* Primary Base Address */
case 0x10:
case 0x11:
@@ -776,9 +783,9 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
/* Datasheet erratum: the PCI BAR's actually have different sizes. */
if (addr == 0x20)
dev->ide_conf[addr] = (val & 0xe0) | 0x01;
- else if ((addr & 0x43) == 0x00)
+ else if ((addr & 0x07) == 0x00)
dev->ide_conf[addr] = (val & 0xf8) | 0x01;
- else if ((addr & 0x43) == 0x40)
+ else if ((addr & 0x07) == 0x04)
dev->ide_conf[addr] = (val & 0xfc) | 0x01;
else
dev->ide_conf[addr] = val;
@@ -887,13 +894,15 @@ ali5229_read(int func, int addr, void *priv)
if (dev->ide_dev_enable && (func == 0)) {
ret = dev->ide_conf[addr];
if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02))
- ret &= 0x0f;
+ ret = (ret & 0x0f) | 0x80;
else if (addr == 0x50)
ret = (ret & 0xfe) | (dev->ide_dev_enable ? 0x01 : 0x00);
else if (addr == 0x75)
ret = ide_read_ali_75();
else if (addr == 0x76)
ret = ide_read_ali_76();
+
+ ali1543_log("M5229: [R] dev->ide_conf[%02x] = %02x\n", addr, ret);
}
return ret;
diff --git a/src/chipset/ali6117.c b/src/chipset/ali6117.c
index c7ada4bc60..cc2e465a2a 100644
--- a/src/chipset/ali6117.c
+++ b/src/chipset/ali6117.c
@@ -471,7 +471,8 @@ ali6117_init(const device_t *info)
dev->local = info->local;
- device_add(&ide_isa_device);
+ if (!(dev->local & 0x08))
+ device_add(&ide_isa_device);
ali6117_setup(dev);
diff --git a/src/chipset/contaq_82c59x.c b/src/chipset/contaq_82c59x.c
index ec7050b1ea..5c29102270 100644
--- a/src/chipset/contaq_82c59x.c
+++ b/src/chipset/contaq_82c59x.c
@@ -311,8 +311,10 @@ contaq_82c59x_close(void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *) priv;
- smram_del(dev->smram[1]);
- smram_del(dev->smram[0]);
+ if (dev->green) {
+ smram_del(dev->smram[1]);
+ smram_del(dev->smram[0]);
+ }
free(dev);
}
diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c
index a1f923e492..2f6afa9402 100644
--- a/src/chipset/intel_4x0.c
+++ b/src/chipset/intel_4x0.c
@@ -493,16 +493,40 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x52: /* Cache Control Register */
switch (dev->type) {
default:
+ /*
+ 420TX/ZX:
+ Bit 7-6: 0, 0 = 64 kB,
+ 0, 1 = 128 kB,
+ 1, 0 = 256 kB,
+ 1, 1 = 512 kB.
+ Bit 5: 1 = L2 cache present, 0 = L2 cache absent.
+ Bit 1: 1 = Write back cache, 0 = write through cache.
+ Bit 0: 1 = L2 cache enable, 0 = L2 cache disable.
+ */
case INTEL_420TX:
case INTEL_420ZX:
+ case INTEL_430NX:
+ regs[0x52] = (regs[0x52] & 0xe0) | (val & 0x1f);
+ cpu_cache_ext_enabled = val & 0x01;
+ cpu_update_waitstates();
+ break;
case INTEL_430LX:
+ regs[0x52] = (regs[0x52] & 0xe0) | (val & 0x1b);
+ cpu_cache_ext_enabled = val & 0x01;
+ cpu_update_waitstates();
+ break;
case INTEL_430FX:
case INTEL_430VX:
case INTEL_430TX:
- regs[0x52] = (val & 0xfb);
+ regs[0x52] = (regs[0x52] & 0x04) | (val & 0xfb);
+ cpu_cache_ext_enabled = ((val & 0x03) == 0x01);
+ cpu_update_waitstates();
break;
- case INTEL_430NX:
case INTEL_430HX:
+ regs[0x52] = val;
+ cpu_cache_ext_enabled = ((val & 0x03) == 0x01);
+ cpu_update_waitstates();
+ break;
case INTEL_440FX:
regs[0x52] = val;
break;
@@ -1630,7 +1654,7 @@ i4x0_init(const device_t *info)
0x00 = None, 0x01 = 64 kB, 0x41 = 128 kB, 0x81 = 256 kB, 0xc1 = 512 kB,
If bit 0 is set, then if bit 2 is also set, the cache is write back,
otherwise it's write through. */
- regs[0x52] = 0xc3; /* 512 kB writeback cache */
+ regs[0x52] = 0xe0; /* 512 kB writeback cache */
regs[0x57] = 0x31;
regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02;
diff --git a/src/chipset/neat.c b/src/chipset/neat.c
index 3b00b4ffde..97c4b8f1a5 100644
--- a/src/chipset/neat.c
+++ b/src/chipset/neat.c
@@ -646,7 +646,8 @@ neat_read(uint16_t port, void *priv)
break;
case 0x23:
- ret = dev->regs[dev->indx];
+ if ((dev->indx >= 0x60) && (dev->indx <= 0x6f))
+ ret = dev->regs[dev->indx];
break;
default:
diff --git a/src/chipset/scat.c b/src/chipset/scat.c
index aa0c5511a3..02610efa25 100644
--- a/src/chipset/scat.c
+++ b/src/chipset/scat.c
@@ -66,15 +66,17 @@ typedef struct ems_page_t {
} ems_page_t;
typedef struct scat_t {
- int type;
+ uint8_t max_reg;
+ uint8_t reg_2xA;
- int indx;
- uint8_t regs[256];
- uint8_t reg_2xA;
+ uint8_t regs[256];
uint32_t xms_bound;
- int external_is_RAS;
+ int type;
+ int indx;
+
+ int external_is_RAS;
ems_page_t null_page;
ems_page_t page[32];
@@ -1233,7 +1235,8 @@ scat_in(uint16_t port, void *priv)
break;
default:
- ret = dev->regs[dev->indx];
+ if (dev->indx <= dev->max_reg)
+ ret = dev->regs[dev->indx];
break;
}
break;
@@ -1393,6 +1396,8 @@ scat_init(const device_t *info)
sx = (dev->type == 32) ? 1 : 0;
+ dev->max_reg = sx ? 0x64 : 0x4f;
+
for (uint32_t i = 0; i < sizeof(dev->regs); i++)
dev->regs[i] = 0xff;
diff --git a/src/chipset/sis_5511.c b/src/chipset/sis_5511.c
index e58066c954..aa841ed9c1 100644
--- a/src/chipset/sis_5511.c
+++ b/src/chipset/sis_5511.c
@@ -25,9 +25,10 @@
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
-
#include <86box/mem.h>
#include <86box/nvr.h>
+#include <86box/apm.h>
+#include <86box/acpi.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -41,7 +42,7 @@
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
-
+#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5511_LOG
@@ -63,856 +64,76 @@ sis_5511_log(const char *fmt, ...)
#endif
typedef struct sis_5511_t {
- uint8_t index;
- uint8_t nb_slot;
- uint8_t sb_slot;
- uint8_t pad;
-
- uint8_t regs[16];
- uint8_t states[7];
+ uint8_t nb_slot;
+ uint8_t sb_slot;
- uint8_t slic_regs[4096];
+ void *h2p;
- uint8_t pci_conf[256];
- uint8_t pci_conf_sb[2][256];
+ void *p2i;
+ void *ide;
- mem_mapping_t slic_mapping;
-
- sff8038i_t *bm[2];
- smram_t *smram;
- port_92_t *port_92;
- void *pit;
- nvr_t *nvr;
-
- uint8_t (*pit_read_reg)(void *priv, uint8_t reg);
+ sis_55xx_common_t *sis;
} sis_5511_t;
static void
-sis_5511_shadow_recalc(sis_5511_t *dev)
-{
- int state;
- uint32_t base;
-
- for (uint8_t i = 0x80; i <= 0x86; i++) {
- if (i == 0x86) {
- if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
- state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
- mem_set_mem_state_both(0xf0000, 0x10000, state);
- sis_5511_log("000F0000-000FFFFF\n");
- }
- } else {
- base = ((i & 0x07) << 15) + 0xc0000;
-
- if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
- state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
- mem_set_mem_state_both(base, 0x4000, state);
- sis_5511_log("%08X-%08X\n", base, base + 0x3fff);
- }
-
- if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
- state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
- mem_set_mem_state_both(base + 0x4000, 0x4000, state);
- sis_5511_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
- }
- }
-
- dev->states[i & 0x0f] = dev->pci_conf[i];
- }
-
- flushmmucache_nopc();
-}
-
-static void
-sis_5511_smram_recalc(sis_5511_t *dev)
-{
- smram_disable_all();
-
- switch (dev->pci_conf[0x65] >> 6) {
- case 0:
- smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
- break;
- case 1:
- smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
- break;
- case 2:
- smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
- break;
-
- default:
- break;
- }
-
- flushmmucache();
-}
-
-static void
-sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv)
+sis_5511_write(int func, int addr, uint8_t val, void *priv)
{
- sis_5511_t *dev = (sis_5511_t *) priv;
+ const sis_5511_t *dev = (sis_5511_t *) priv;
sis_5511_log("SiS 5511: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
- if (func == 0x00) switch (addr) {
- case 0x07: /* Status - High Byte */
- dev->pci_conf[addr] &= 0xb0;
- break;
-
- case 0x50:
- dev->pci_conf[addr] = val;
- cpu_cache_ext_enabled = !!(val & 0x40);
- cpu_update_waitstates();
- break;
-
- case 0x51:
- dev->pci_conf[addr] = val & 0xfe;
- break;
-
- case 0x52:
- dev->pci_conf[addr] = val & 0x3f;
- break;
-
- case 0x53:
- case 0x54:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x55:
- dev->pci_conf[addr] = val & 0xf8;
- break;
-
- case 0x56 ... 0x59:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x5a:
- /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC.
- The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h.
- The latter (bit 6) means the chipset intercepts all odd FXh to 64h.
- Bit 5 sets fast reset latency. This should be fixed on the other SiS
- chipsets as well. */
- dev->pci_conf[addr] = val;
- break;
-
- case 0x5b:
- dev->pci_conf[addr] = val & 0xf7;
- break;
-
- case 0x5c:
- dev->pci_conf[addr] = val & 0xcf;
- break;
-
- case 0x5d:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x5e:
- dev->pci_conf[addr] = val & 0xfe;
- break;
-
- case 0x5f:
- dev->pci_conf[addr] = val & 0xfe;
- break;
-
- case 0x60:
- dev->pci_conf[addr] = val & 0x3e;
- if ((dev->pci_conf[0x68] & 1) && (val & 2)) {
- smi_raise();
- dev->pci_conf[0x69] |= 1;
- }
- break;
-
- case 0x61 ... 0x64:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x65:
- dev->pci_conf[addr] = val & 0xd0;
- sis_5511_smram_recalc(dev);
- break;
-
- case 0x66:
- dev->pci_conf[addr] = val & 0x7f;
- break;
-
- case 0x67:
- case 0x68:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x69:
- dev->pci_conf[addr] &= val;
- break;
-
- case 0x6a ... 0x6e:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x6f:
- dev->pci_conf[addr] = val & 0x3f;
- break;
-
- case 0x70: /* DRAM Bank Register 0-0 */
- case 0x72: /* DRAM Bank Register 0-1 */
- case 0x74: /* DRAM Bank Register 1-0 */
- case 0x76: /* DRAM Bank Register 1-1 */
- case 0x78: /* DRAM Bank Register 2-0 */
- case 0x7a: /* DRAM Bank Register 2-1 */
- case 0x7c: /* DRAM Bank Register 3-0 */
- case 0x7e: /* DRAM Bank Register 3-1 */
- spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82);
- break;
-
- case 0x71: /* DRAM Bank Register 0-0 */
- dev->pci_conf[addr] = val;
- break;
-
- case 0x75: /* DRAM Bank Register 1-0 */
- case 0x79: /* DRAM Bank Register 2-0 */
- case 0x7d: /* DRAM Bank Register 3-0 */
- dev->pci_conf[addr] = val & 0x7f;
- break;
-
- case 0x73: /* DRAM Bank Register 0-1 */
- case 0x77: /* DRAM Bank Register 1-1 */
- case 0x7b: /* DRAM Bank Register 2-1 */
- case 0x7f: /* DRAM Bank Register 3-1 */
- dev->pci_conf[addr] = val & 0x83;
- break;
-
- case 0x80 ... 0x85:
- dev->pci_conf[addr] = val & 0xee;
- sis_5511_shadow_recalc(dev);
- break;
- case 0x86:
- dev->pci_conf[addr] = val & 0xe8;
- sis_5511_shadow_recalc(dev);
- break;
-
- case 0x90 ... 0x93: /* 5512 General Purpose Register Index */
- dev->pci_conf[addr] = val;
- break;
-
- default:
- break;
- }
-}
-
-static void
-sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv)
-{
- sis_5511_t *dev = (sis_5511_t *) priv;
-
- addr &= 0x00000fff;
-
- switch (addr) {
- case 0x00000000:
- case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
- dev->slic_regs[addr] = val;
- break;
- case 0x00000010:
- case 0x00000018:
- case 0x00000028:
- case 0x00000038:
- dev->slic_regs[addr] = val & 0x01;
- break;
- case 0x00000030:
- dev->slic_regs[addr] = val & 0x0f;
- mem_mapping_set_addr(&dev->slic_mapping,
- (((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000);
- break;
- }
+ if (func == 0x00)
+ sis_5511_host_to_pci_write(addr, val, dev->h2p);
}
static uint8_t
-sis_5511_read(UNUSED(int func), int addr, void *priv)
+sis_5511_read(int func, int addr, void *priv)
{
const sis_5511_t *dev = (sis_5511_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
- ret = dev->pci_conf[addr];
+ ret = sis_5511_host_to_pci_read(addr, dev->h2p);
sis_5511_log("SiS 5511: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
-static uint8_t
-sis_5511_slic_read(uint32_t addr, void *priv)
-{
- sis_5511_t *dev = (sis_5511_t *) priv;
- uint8_t ret = 0xff;
-
- addr &= 0x00000fff;
-
- switch (addr) {
- case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
- ret = dev->slic_regs[addr];
- break;
- }
-
- return ret;
-}
-
-void
-sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev)
-{
- sis_5511_log("SiS 5513 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val);
-
- switch (addr) {
- case 0x04: /* Command */
- dev->pci_conf_sb[0][addr] = val & 0x0f;
- break;
-
- case 0x07: /* Status */
- dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x06) & ~(val & 0x30);
- break;
-
- case 0x40: /* BIOS Control Register */
- dev->pci_conf_sb[0][addr] = val & 0x3f;
- break;
-
- case 0x41: /* INTA# Remapping Control Register */
- case 0x42: /* INTB# Remapping Control Register */
- case 0x43: /* INTC# Remapping Control Register */
- case 0x44: /* INTD# Remapping Control Register */
- dev->pci_conf_sb[0][addr] = val & 0x8f;
- pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f));
- break;
-
- case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
- case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
- case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
- case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x60: /* MIRQ0 Remapping Control Register */
- case 0x61: /* MIRQ1 Remapping Control Register */
- sis_5511_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val);
- dev->pci_conf_sb[0][addr] = val & 0xcf;
- if (val & 0x80)
- pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED);
- else
- pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
- break;
-
- case 0x62: /* On-board Device DMA Control Register */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x63: /* IDEIRQ Remapping Control Register */
- sis_5511_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
- dev->pci_conf_sb[0][addr] = val & 0x8f;
- if (val & 0x80)
- pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
- else
- pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
- break;
-
- case 0x64: /* GPIO0 Control Register */
- dev->pci_conf_sb[0][addr] = val & 0xef;
- break;
-
- case 0x65:
- dev->pci_conf_sb[0][addr] = val & 0x80;
- break;
-
- case 0x66: /* GPIO0 Output Mode Control Register */
- case 0x67: /* GPIO0 Output Mode Control Register */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x6a: /* GPIO Status Register */
- dev->pci_conf_sb[0][addr] |= (val & 0x10);
- dev->pci_conf_sb[0][addr] &= ~(val & 0x01);
- break;
-
- default:
- break;
- }
-}
-
-static void
-sis_5513_ide_irq_handler(sis_5511_t *dev)
-{
- if (dev->pci_conf_sb[1][0x09] & 0x01) {
- /* Primary IDE is native. */
- sis_5511_log("Primary IDE IRQ mode: Native, Native\n");
- sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X);
- } else {
- /* Primary IDE is legacy. */
- sis_5511_log("Primary IDE IRQ mode: IRQ14, IRQ15\n");
- sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY);
- }
-
- if (dev->pci_conf_sb[1][0x09] & 0x04) {
- /* Secondary IDE is native. */
- sis_5511_log("Secondary IDE IRQ mode: Native, Native\n");
- sff_set_irq_mode(dev->bm[1], IRQ_MODE_SIS_551X);
- } else {
- /* Secondary IDE is legacy. */
- sis_5511_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n");
- sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
- }
-}
-
-static void
-sis_5513_ide_handler(sis_5511_t *dev)
-{
- uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01;
-
- uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe;
- uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe;
- uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe;
- uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe;
-
- uint16_t current_pri_base;
- uint16_t current_pri_side;
- uint16_t current_sec_base;
- uint16_t current_sec_side;
-
- /* Primary Channel Programming */
- current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr;
- current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr;
-
- /* Secondary Channel Programming */
- current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr;
- current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr;
-
- sis_5511_log("sis_5513_ide_handler(): Disabling primary IDE...\n");
- ide_pri_disable();
- sis_5511_log("sis_5513_ide_handler(): Disabling secondary IDE...\n");
- ide_sec_disable();
-
- if (ide_io_on) {
- /* Primary Channel Setup */
- if (dev->pci_conf_sb[1][0x4a] & 0x02) {
- sis_5511_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base);
- ide_set_base(0, current_pri_base);
- sis_5511_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side);
- ide_set_side(0, current_pri_side);
-
- sis_5511_log("sis_5513_ide_handler(): Enabling primary IDE...\n");
- ide_pri_enable();
-
- sis_5511_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side);
- }
-
- /* Secondary Channel Setup */
- if (dev->pci_conf_sb[1][0x4a] & 0x04) {
- sis_5511_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base);
- ide_set_base(1, current_sec_base);
- sis_5511_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side);
- ide_set_side(1, current_sec_side);
-
- sis_5511_log("sis_5513_ide_handler(): Enabling secondary IDE...\n");
- ide_sec_enable();
-
- sis_5511_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side);
- }
- }
-
- sff_bus_master_handler(dev->bm[0], ide_io_on,
- ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0);
- sff_bus_master_handler(dev->bm[1], ide_io_on,
- ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8);
-}
-
-void
-sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev)
-{
- sis_5511_log("SiS 5513 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val);
-
- switch (addr) {
- case 0x04: /* Command low byte */
- dev->pci_conf_sb[1][addr] = val & 0x05;
- sis_5513_ide_handler(dev);
- break;
- case 0x06: /* Status low byte */
- dev->pci_conf_sb[1][addr] = val & 0x20;
- break;
- case 0x07: /* Status high byte */
- dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38);
- break;
- case 0x09: /* Programming Interface Byte */
- dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x05);
- sis_5513_ide_irq_handler(dev);
- sis_5513_ide_handler(dev);
- break;
- case 0x0d: /* Latency Timer */
- dev->pci_conf_sb[1][addr] = val;
- break;
-
- /* Primary Base Address */
- case 0x10:
- case 0x11:
- case 0x14:
- case 0x15:
- fallthrough;
-
- /* Secondary Base Address */
- case 0x18:
- case 0x19:
- case 0x1c:
- case 0x1d:
- fallthrough;
-
- /* Bus Mastering Base Address */
- case 0x20:
- case 0x21:
- if (addr == 0x20)
- dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01;
- else
- dev->pci_conf_sb[1][addr] = val;
- sis_5513_ide_handler(dev);
- break;
-
- case 0x30: /* Expansion ROM Base Address */
- case 0x31: /* Expansion ROM Base Address */
- case 0x32: /* Expansion ROM Base Address */
- case 0x33: /* Expansion ROM Base Address */
- dev->pci_conf_sb[1][addr] = val;
- break;
-
- case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
- case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
- case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
- case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
- case 0x48: /* IDE Command Recovery Time Control */
- dev->pci_conf_sb[1][addr] = val & 0x0f;
- break;
-
- case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
- case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
- case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
- case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
- case 0x49: /* IDE Command Active Time Control */
- dev->pci_conf_sb[1][addr] = val & 0x07;
- break;
-
- case 0x4a: /* IDE General Control Register 0 */
- dev->pci_conf_sb[1][addr] = val & 0x9e;
- sis_5513_ide_handler(dev);
- break;
-
- case 0x4b: /* IDE General Control Register 1 */
- dev->pci_conf_sb[1][addr] = val & 0xef;
- break;
-
- case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
- case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
- case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
- case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
- dev->pci_conf_sb[1][addr] = val;
- break;
-
- default:
- break;
- }
-}
-
static void
sis_5513_write(int func, int addr, uint8_t val, void *priv)
-{
- sis_5511_t *dev = (sis_5511_t *) priv;
-
- switch (func) {
- default:
- break;
- case 0:
- sis_5513_pci_to_isa_write(addr, val, dev);
- break;
- case 1:
- sis_5513_ide_write(addr, val, dev);
- break;
- }
-}
-
-static uint8_t
-sis_5513_read(int func, int addr, void *priv)
{
const sis_5511_t *dev = (sis_5511_t *) priv;
- uint8_t ret = 0xff;
- if (func == 0x00) {
- switch (addr) {
- default:
- ret = dev->pci_conf_sb[func][addr];
- break;
- case 0x4c ... 0x4f:
- ret = pic_read_icw(0, addr & 0x03);
- break;
- case 0x50 ... 0x53:
- ret = pic_read_icw(1, addr & 0x03);
- break;
- case 0x54 ... 0x55:
- ret = pic_read_ocw(0, addr & 0x01);
- break;
- case 0x56 ... 0x57:
- ret = pic_read_ocw(1, addr & 0x01);
- break;
- case 0x58 ... 0x5f:
- ret = dev->pit_read_reg(dev->pit, addr & 0x07);
- break;
- }
+ sis_5511_log("SiS 5513: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
- sis_5511_log("SiS 5513 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret);
- } else if (func == 0x01) {
- if (addr == 0x3d)
- ret = (((dev->pci_conf_sb[0x01][0x4b] & 0xc0) == 0xc0) ||
- (dev->pci_conf_sb[0x01][0x09] & 0x05)) ? PCI_INTA : 0x00;
- else
- ret = dev->pci_conf_sb[func][addr];
-
- sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret);
- }
-
- return ret;
-}
-
-static void
-sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv)
-{
- sis_5511_t *dev = (sis_5511_t *) priv;
-
- switch (addr) {
- case 0x22:
- dev->index = val - 0x50;
- break;
- case 0x23:
- sis_5511_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val);
-
- switch (dev->index) {
- case 0x00:
- dev->regs[dev->index] = val & 0xed;
- switch (val >> 6) {
- case 0:
- cpu_set_isa_speed(7159091);
- break;
- case 1:
- cpu_set_isa_pci_div(4);
- break;
- case 2:
- cpu_set_isa_pci_div(3);
- break;
-
- default:
- break;
- }
- nvr_bank_set(0, !!(val & 0x08), dev->nvr);
- break;
- case 0x01:
- dev->regs[dev->index] = val & 0xf4;
- break;
- case 0x03:
- dev->regs[dev->index] = val & 3;
- break;
- case 0x04: /* BIOS Register */
- dev->regs[dev->index] = val;
- break;
- case 0x05:
- dev->regs[dev->index] = val;
- outb(0x70, val);
- break;
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- dev->regs[dev->index] = val;
- break;
-
- default:
- break;
- }
- break;
-
- default:
- break;
- }
+ if (func == 0x00)
+ sis_5513_pci_to_isa_write(addr, val, dev->p2i);
+ else if (func == 0x01)
+ sis_5513_ide_write(addr, val, dev->ide);
}
static uint8_t
-sis_5513_isa_read(uint16_t addr, void *priv)
+sis_5513_read(int func, int addr, void *priv)
{
const sis_5511_t *dev = (sis_5511_t *) priv;
uint8_t ret = 0xff;
- if (addr == 0x23) {
- if (dev->index == 0x05)
- ret = inb(0x70);
- else
- ret = dev->regs[dev->index];
+ if (func == 0x00)
+ ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
+ else if (func == 0x01)
+ ret = sis_5513_ide_read(addr, dev->ide);
- sis_5511_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret);
- }
+ sis_5511_log("SiS 5513: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
-static void
-sis_5511_reset(void *priv)
-{
- sis_5511_t *dev = (sis_5511_t *) priv;
-
- /* SiS 5511 */
- dev->pci_conf[0x00] = 0x39;
- dev->pci_conf[0x01] = 0x10;
- dev->pci_conf[0x02] = 0x11;
- dev->pci_conf[0x03] = 0x55;
- dev->pci_conf[0x04] = 0x07;
- dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
- dev->pci_conf[0x07] = 0x02;
- dev->pci_conf[0x08] = 0x00;
- dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
- dev->pci_conf[0x0b] = 0x06;
- dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
- dev->pci_conf[0x52] = 0x20;
- dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00;
- dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00;
- dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
- dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
- dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00;
- dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00;
- dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00;
- dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff;
- dev->pci_conf[0x63] = 0xff;
- dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
- dev->pci_conf[0x66] = 0x00;
- dev->pci_conf[0x67] = 0xff;
- dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
- dev->pci_conf[0x6a] = 0x00;
- dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff;
- dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff;
- dev->pci_conf[0x6f] = 0x00;
- dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04;
- dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04;
- dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04;
- dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04;
- dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00;
- dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80;
- dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00;
- dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80;
- dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
- dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
- dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00;
- dev->pci_conf[0x86] = 0x00;
-
- cpu_cache_ext_enabled = 0;
- cpu_update_waitstates();
-
- sis_5511_smram_recalc(dev);
- sis_5511_shadow_recalc(dev);
-
- flushmmucache();
-
- memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t));
- dev->slic_regs[0x18] = 0x0f;
-
- mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000);
-
- /* SiS 5513 */
- dev->pci_conf_sb[0][0x00] = 0x39;
- dev->pci_conf_sb[0][0x01] = 0x10;
- dev->pci_conf_sb[0][0x02] = 0x08;
- dev->pci_conf_sb[0][0x03] = 0x00;
- dev->pci_conf_sb[0][0x04] = 0x07;
- dev->pci_conf_sb[0][0x05] = dev->pci_conf_sb[0][0x06] = 0x00;
- dev->pci_conf_sb[0][0x07] = 0x02;
- dev->pci_conf_sb[0][0x08] = dev->pci_conf_sb[0][0x09] = 0x00;
- dev->pci_conf_sb[0][0x0a] = 0x01;
- dev->pci_conf_sb[0][0x0b] = 0x06;
- dev->pci_conf_sb[0][0x0e] = 0x80;
- dev->pci_conf_sb[0][0x40] = 0x00;
- dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80;
- dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80;
- dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x00;
- dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00;
- dev->pci_conf_sb[0][0x60] = dev->pci_conf_sb[0][0x61] = 0x80;
- dev->pci_conf_sb[0][0x62] = 0x00;
- dev->pci_conf_sb[0][0x63] = 0x80;
- dev->pci_conf_sb[0][0x64] = 0x00;
- dev->pci_conf_sb[0][0x65] = 0x00;
- dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00;
- dev->pci_conf_sb[0][0x68] = dev->pci_conf_sb[0][0x69] = 0x00;
- dev->pci_conf_sb[0][0x6a] = 0x04;
-
- pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
- pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
- pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
- pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
-
- pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
- pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
- pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
-
- dev->regs[0x00] = dev->regs[0x01] = 0x00;
- dev->regs[0x03] = dev->regs[0x04] = 0x00;
- dev->regs[0x05] = 0x00;
- dev->regs[0x08] = dev->regs[0x09] = 0x00;
- dev->regs[0x0a] = dev->regs[0x0b] = 0x00;
-
- cpu_set_isa_speed(7159091);
- nvr_bank_set(0, 0, dev->nvr);
-
- /* SiS 5513 IDE Controller */
- dev->pci_conf_sb[1][0x00] = 0x39;
- dev->pci_conf_sb[1][0x01] = 0x10;
- dev->pci_conf_sb[1][0x02] = 0x13;
- dev->pci_conf_sb[1][0x03] = 0x55;
- dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00;
- dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00;
- dev->pci_conf_sb[1][0x08] = 0x00;
- dev->pci_conf_sb[1][0x09] = 0x8a;
- dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01;
- dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00;
- dev->pci_conf_sb[1][0x0e] = 0x80;
- dev->pci_conf_sb[1][0x0f] = 0x00;
- dev->pci_conf_sb[1][0x10] = 0xf1;
- dev->pci_conf_sb[1][0x11] = 0x01;
- dev->pci_conf_sb[1][0x14] = 0xf5;
- dev->pci_conf_sb[1][0x15] = 0x03;
- dev->pci_conf_sb[1][0x18] = 0x71;
- dev->pci_conf_sb[1][0x19] = 0x01;
- dev->pci_conf_sb[1][0x1c] = 0x75;
- dev->pci_conf_sb[1][0x1d] = 0x03;
- dev->pci_conf_sb[1][0x20] = 0x01;
- dev->pci_conf_sb[1][0x21] = 0xf0;
- dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00;
- dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00;
- dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00;
- dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00;
- dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00;
- dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00;
- dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00;
- dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00;
- dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00;
- dev->pci_conf_sb[1][0x40] = dev->pci_conf_sb[1][0x41] = 0x00;
- dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00;
- dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00;
- dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00;
- dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00;
- dev->pci_conf_sb[1][0x4a] = 0x06;
- dev->pci_conf_sb[1][0x4b] = 0x00;
- dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00;
- dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00;
-
- sis_5513_ide_irq_handler(dev);
- sis_5513_ide_handler(dev);
-
- sff_bus_master_reset(dev->bm[0]);
- sff_bus_master_reset(dev->bm[1]);
-}
-
static void
sis_5511_close(void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
- smram_del(dev->smram);
free(dev);
}
@@ -920,53 +141,18 @@ static void *
sis_5511_init(UNUSED(const device_t *info))
{
sis_5511_t *dev = (sis_5511_t *) calloc(1, sizeof(sis_5511_t));
- uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
/* Device 0: SiS 5511 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot);
/* Device 1: SiS 5513 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot);
- /* SLiC Memory Mapped Registers */
- mem_mapping_add(&dev->slic_mapping,
- 0xffc00000, 0x00001000,
- sis_5511_slic_read,
- NULL,
- NULL,
- sis_5511_slic_write,
- NULL,
- NULL,
- NULL, MEM_MAPPING_EXTERNAL,
- dev);
-
- /* Ports 22h-23h: SiS 5513 ISA */
- io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev);
-
- /* MIRQ */
- pci_enable_mirq(0);
- pci_enable_mirq(1);
-
- /* IDEIRQ */
- pci_enable_mirq(2);
-
- /* Port 92h */
- dev->port_92 = device_add(&port_92_device);
-
- /* SFF IDE */
- dev->bm[0] = device_add_inst(&sff8038i_device, 1);
- dev->bm[1] = device_add_inst(&sff8038i_device, 2);
-
- /* SMRAM */
- dev->smram = smram_add();
-
- /* PIT */
- dev->pit = device_find_first_priv(DEVICE_PIT);
- dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg;
+ dev->sis = device_add(&sis_55xx_common_device);
- /* NVR */
- dev->nvr = device_add(&at_mb_nvr_device);
+ dev->h2p = device_add_linked(&sis_5511_h2p_device, dev->sis);
- sis_5511_reset(dev);
+ dev->p2i = device_add_linked(&sis_5513_p2i_device, dev->sis);
+ dev->ide = device_add_linked(&sis_5513_ide_device, dev->sis);
return dev;
}
@@ -978,7 +164,7 @@ const device_t sis_5511_device = {
.local = 0,
.init = sis_5511_init,
.close = sis_5511_close,
- .reset = sis_5511_reset,
+ .reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
diff --git a/src/chipset/sis_5511_h2p.c b/src/chipset/sis_5511_h2p.c
new file mode 100644
index 0000000000..7916d6ae29
--- /dev/null
+++ b/src/chipset/sis_5511_h2p.c
@@ -0,0 +1,461 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5511 Host to PCI bridge.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/spd.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+#include <86box/agpgart.h>
+
+#ifdef ENABLE_SIS_5511_HOST_TO_PCI_LOG
+int sis_5511_host_to_pci_do_log = ENABLE_SIS_5511_HOST_TO_PCI_LOG;
+
+static void
+sis_5511_host_to_pci_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5511_host_to_pci_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5511_host_to_pci_log(fmt, ...)
+#endif
+
+typedef struct sis_5511_host_to_pci_t {
+ uint8_t pci_conf[256];
+ uint8_t states[7];
+
+ uint8_t slic_regs[4096];
+
+ sis_55xx_common_t *sis;
+
+ smram_t *smram;
+
+ mem_mapping_t slic_mapping;
+} sis_5511_host_to_pci_t;
+
+static void
+sis_5511_shadow_recalc(sis_5511_host_to_pci_t *dev)
+{
+ int state;
+ uint32_t base;
+
+ for (uint8_t i = 0x80; i <= 0x86; i++) {
+ if (i == 0x86) {
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
+ state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(0xf0000, 0x10000, state);
+ sis_5511_host_to_pci_log("000F0000-000FFFFF\n");
+ }
+ } else {
+ base = ((i & 0x07) << 15) + 0xc0000;
+
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
+ state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(base, 0x4000, state);
+ sis_5511_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+ }
+
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
+ state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(base + 0x4000, 0x4000, state);
+ sis_5511_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
+ }
+ }
+
+ dev->states[i & 0x0f] = dev->pci_conf[i];
+ }
+
+ flushmmucache_nopc();
+}
+
+static void
+sis_5511_smram_recalc(sis_5511_host_to_pci_t *dev)
+{
+ smram_disable_all();
+
+ switch (dev->pci_conf[0x65] >> 6) {
+ case 0:
+ smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
+ break;
+ case 1:
+ smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
+ break;
+ case 2:
+ smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
+ break;
+
+ default:
+ break;
+ }
+
+ flushmmucache();
+}
+
+void
+sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv)
+{
+ sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
+
+ sis_5511_host_to_pci_log("SiS 5511 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ default:
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] &= 0xb0;
+ break;
+
+ case 0x50:
+ dev->pci_conf[addr] = val;
+ cpu_cache_ext_enabled = !!(val & 0x40);
+ cpu_update_waitstates();
+ break;
+
+ case 0x51:
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x52:
+ dev->pci_conf[addr] = val & 0x3f;
+ break;
+
+ case 0x53:
+ case 0x54:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x55:
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x56 ... 0x59:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x5a:
+ /* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC.
+ The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h.
+ The latter (bit 6) means the chipset intercepts all odd FXh to 64h.
+ Bit 5 sets fast reset latency. This should be fixed on the other SiS
+ chipsets as well. */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x5b:
+ dev->pci_conf[addr] = val & 0xf7;
+ break;
+
+ case 0x5c:
+ dev->pci_conf[addr] = val & 0xcf;
+ break;
+
+ case 0x5d:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x5e:
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x5f:
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x60:
+ dev->pci_conf[addr] = val & 0x3e;
+ if ((dev->pci_conf[0x68] & 1) && (val & 2)) {
+ smi_raise();
+ dev->pci_conf[0x69] |= 1;
+ }
+ break;
+
+ case 0x61 ... 0x64:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x65:
+ dev->pci_conf[addr] = val & 0xd0;
+ sis_5511_smram_recalc(dev);
+ break;
+
+ case 0x66:
+ dev->pci_conf[addr] = val & 0x7f;
+ break;
+
+ case 0x67:
+ case 0x68:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x69:
+ dev->pci_conf[addr] &= val;
+ break;
+
+ case 0x6a ... 0x6e:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6f:
+ dev->pci_conf[addr] = val & 0x3f;
+ break;
+
+ case 0x70: /* DRAM Bank Register 0-0 */
+ case 0x72: /* DRAM Bank Register 0-1 */
+ case 0x74: /* DRAM Bank Register 1-0 */
+ case 0x76: /* DRAM Bank Register 1-1 */
+ case 0x78: /* DRAM Bank Register 2-0 */
+ case 0x7a: /* DRAM Bank Register 2-1 */
+ case 0x7c: /* DRAM Bank Register 3-0 */
+ case 0x7e: /* DRAM Bank Register 3-1 */
+ spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82);
+ break;
+
+ case 0x71: /* DRAM Bank Register 0-0 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x75: /* DRAM Bank Register 1-0 */
+ case 0x79: /* DRAM Bank Register 2-0 */
+ case 0x7d: /* DRAM Bank Register 3-0 */
+ dev->pci_conf[addr] = val & 0x7f;
+ break;
+
+ case 0x73: /* DRAM Bank Register 0-1 */
+ case 0x77: /* DRAM Bank Register 1-1 */
+ case 0x7b: /* DRAM Bank Register 2-1 */
+ case 0x7f: /* DRAM Bank Register 3-1 */
+ dev->pci_conf[addr] = val & 0x83;
+ break;
+
+ case 0x80 ... 0x85:
+ dev->pci_conf[addr] = val & 0xee;
+ sis_5511_shadow_recalc(dev);
+ break;
+ case 0x86:
+ dev->pci_conf[addr] = val & 0xe8;
+ sis_5511_shadow_recalc(dev);
+ break;
+
+ case 0x90 ... 0x93: /* 5512 General Purpose Register Index */
+ dev->pci_conf[addr] = val;
+ break;
+ }
+}
+
+uint8_t
+sis_5511_host_to_pci_read(int addr, void *priv)
+{
+ const sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
+ uint8_t ret = 0xff;
+
+ ret = dev->pci_conf[addr];
+
+ sis_5511_host_to_pci_log("SiS 5511 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv)
+{
+ sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
+
+ addr &= 0x00000fff;
+
+ switch (addr) {
+ case 0x00000000:
+ case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
+ dev->slic_regs[addr] = val;
+ break;
+ case 0x00000010:
+ case 0x00000018:
+ case 0x00000028:
+ case 0x00000038:
+ dev->slic_regs[addr] = val & 0x01;
+ break;
+ case 0x00000030:
+ dev->slic_regs[addr] = val & 0x0f;
+ mem_mapping_set_addr(&dev->slic_mapping,
+ (((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000);
+ break;
+ }
+}
+
+static uint8_t
+sis_5511_slic_read(uint32_t addr, void *priv)
+{
+ sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
+ uint8_t ret = 0xff;
+
+ addr &= 0x00000fff;
+
+ switch (addr) {
+ case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
+ ret = dev->slic_regs[addr];
+ break;
+ }
+
+ return ret;
+}
+
+static void
+sis_5511_host_to_pci_reset(void *priv)
+{
+ sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x11;
+ dev->pci_conf[0x03] = 0x55;
+ dev->pci_conf[0x04] = 0x07;
+ dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x00;
+ dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
+ dev->pci_conf[0x52] = 0x20;
+ dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00;
+ dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00;
+ dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
+ dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
+ dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00;
+ dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00;
+ dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00;
+ dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff;
+ dev->pci_conf[0x63] = 0xff;
+ dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x66] = 0x00;
+ dev->pci_conf[0x67] = 0xff;
+ dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
+ dev->pci_conf[0x6a] = 0x00;
+ dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff;
+ dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff;
+ dev->pci_conf[0x6f] = 0x00;
+ dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04;
+ dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04;
+ dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04;
+ dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04;
+ dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80;
+ dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00;
+ dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80;
+ dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
+ dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00;
+ dev->pci_conf[0x86] = 0x00;
+
+ cpu_cache_ext_enabled = 0;
+ cpu_update_waitstates();
+
+ sis_5511_smram_recalc(dev);
+ sis_5511_shadow_recalc(dev);
+
+ flushmmucache();
+
+ memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t));
+ dev->slic_regs[0x18] = 0x0f;
+
+ mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000);
+}
+
+static void
+sis_5511_host_to_pci_close(void *priv)
+{
+ sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+static void *
+sis_5511_host_to_pci_init(UNUSED(const device_t *info))
+{
+ sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) calloc(1, sizeof(sis_5511_host_to_pci_t));
+
+ dev->sis = device_get_common_priv();
+
+ /* SLiC Memory Mapped Registers */
+ mem_mapping_add(&dev->slic_mapping,
+ 0xffc00000, 0x00001000,
+ sis_5511_slic_read,
+ NULL,
+ NULL,
+ sis_5511_slic_write,
+ NULL,
+ NULL,
+ NULL, MEM_MAPPING_EXTERNAL,
+ dev);
+
+ /* SMRAM */
+ dev->smram = smram_add();
+
+ sis_5511_host_to_pci_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5511_h2p_device = {
+ .name = "SiS 5511 Host to PCI bridge",
+ .internal_name = "sis_5511_host_to_pci",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5511_host_to_pci_init,
+ .close = sis_5511_host_to_pci_close,
+ .reset = sis_5511_host_to_pci_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5513_ide.c b/src/chipset/sis_5513_ide.c
new file mode 100644
index 0000000000..5cbfbdea86
--- /dev/null
+++ b/src/chipset/sis_5513_ide.c
@@ -0,0 +1,505 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5513 IDE controller.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+
+#ifdef ENABLE_SIS_5513_IDE_LOG
+int sis_5513_ide_do_log = ENABLE_SIS_5513_IDE_LOG;
+
+static void
+sis_5513_ide_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5513_ide_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5513_ide_log(fmt, ...)
+#endif
+
+typedef struct sis_5513_ide_t {
+ uint8_t rev;
+
+ uint8_t pci_conf[256];
+
+ sis_55xx_common_t *sis;
+} sis_5513_ide_t;
+
+static void
+sis_5513_ide_irq_handler(sis_5513_ide_t *dev)
+{
+ if (dev->pci_conf[0x09] & 0x01) {
+ /* Primary IDE is native. */
+ sis_5513_ide_log("Primary IDE IRQ mode: Native, Native\n");
+ sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_SIS_551X);
+ } else {
+ /* Primary IDE is legacy. */
+ sis_5513_ide_log("Primary IDE IRQ mode: IRQ14, IRQ15\n");
+ sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_LEGACY);
+ }
+
+ if (dev->pci_conf[0x09] & 0x04) {
+ /* Secondary IDE is native. */
+ sis_5513_ide_log("Secondary IDE IRQ mode: Native, Native\n");
+ sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_SIS_551X);
+ } else {
+ /* Secondary IDE is legacy. */
+ sis_5513_ide_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n");
+ sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_LEGACY);
+ }
+}
+
+static void
+sis_5513_ide_handler(sis_5513_ide_t *dev)
+{
+ uint8_t ide_io_on = dev->pci_conf[0x04] & 0x01;
+
+ uint16_t native_base_pri_addr = (dev->pci_conf[0x11] | dev->pci_conf[0x10] << 8) & 0xfffe;
+ uint16_t native_side_pri_addr = (dev->pci_conf[0x15] | dev->pci_conf[0x14] << 8) & 0xfffe;
+ uint16_t native_base_sec_addr = (dev->pci_conf[0x19] | dev->pci_conf[0x18] << 8) & 0xfffe;
+ uint16_t native_side_sec_addr = (dev->pci_conf[0x1c] | dev->pci_conf[0x1b] << 8) & 0xfffe;
+
+ uint16_t current_pri_base;
+ uint16_t current_pri_side;
+ uint16_t current_sec_base;
+ uint16_t current_sec_side;
+
+ /* Primary Channel Programming */
+ current_pri_base = (!(dev->pci_conf[0x09] & 1)) ? 0x01f0 : native_base_pri_addr;
+ current_pri_side = (!(dev->pci_conf[0x09] & 1)) ? 0x03f6 : native_side_pri_addr;
+
+ /* Secondary Channel Programming */
+ current_sec_base = (!(dev->pci_conf[0x09] & 4)) ? 0x0170 : native_base_sec_addr;
+ current_sec_side = (!(dev->pci_conf[0x09] & 4)) ? 0x0376 : native_side_sec_addr;
+
+ sis_5513_ide_log("sis_5513_ide_handler(): Disabling primary IDE...\n");
+ ide_pri_disable();
+ sis_5513_ide_log("sis_5513_ide_handler(): Disabling secondary IDE...\n");
+ ide_sec_disable();
+
+ if (ide_io_on) {
+ /* Primary Channel Setup */
+ if (dev->pci_conf[0x4a] & 0x02) {
+ sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base);
+ ide_set_base(0, current_pri_base);
+ sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side);
+ ide_set_side(0, current_pri_side);
+
+ sis_5513_ide_log("sis_5513_ide_handler(): Enabling primary IDE...\n");
+ ide_pri_enable();
+
+ sis_5513_ide_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side);
+ }
+
+ /* Secondary Channel Setup */
+ if (dev->pci_conf[0x4a] & 0x04) {
+ sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base);
+ ide_set_base(1, current_sec_base);
+ sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side);
+ ide_set_side(1, current_sec_side);
+
+ sis_5513_ide_log("sis_5513_ide_handler(): Enabling secondary IDE...\n");
+ ide_sec_enable();
+
+ sis_5513_ide_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side);
+ }
+ }
+
+ sff_bus_master_handler(dev->sis->bm[0], ide_io_on,
+ ((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 0);
+ sff_bus_master_handler(dev->sis->bm[1], ide_io_on,
+ ((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 8);
+}
+
+void
+sis_5513_ide_write(int addr, uint8_t val, void *priv)
+{
+ sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
+
+ sis_5513_ide_log("SiS 5513 IDE: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ case 0x04: /* Command low byte */
+ dev->pci_conf[addr] = val & 0x05;
+ sis_5513_ide_handler(dev);
+ break;
+ case 0x06: /* Status low byte */
+ dev->pci_conf[addr] = val & 0x20;
+ break;
+ case 0x07: /* Status high byte */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x38);
+ break;
+ case 0x09: /* Programming Interface Byte */
+ switch (dev->rev) {
+ case 0xd0:
+ if (dev->sis->ide_bits_1_3_writable)
+ val |= 0x0a;
+ fallthrough;
+ case 0x00:
+ case 0xd1:
+ val &= 0xbf;
+ fallthrough;
+ case 0xc0:
+ switch (val & 0x0a) {
+ case 0x00:
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x85) | (val & 0x4a);
+ break;
+ case 0x02:
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x84) | (val & 0x4b);
+ break;
+ case 0x08:
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x81) | (val & 0x4e);
+ break;
+ case 0x0a:
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x80) | (val & 0x4f);
+ break;
+ }
+ break;
+ }
+ sis_5513_ide_irq_handler(dev);
+ sis_5513_ide_handler(dev);
+ break;
+ case 0x0d: /* Latency Timer */
+ dev->pci_conf[addr] = val;
+ break;
+
+ /* Primary Base Address */
+ case 0x10 ... 0x11:
+ case 0x14 ... 0x15:
+ fallthrough;
+
+ /* Secondary Base Address */
+ case 0x18 ... 0x19:
+ case 0x1c ... 0x1d:
+ fallthrough;
+
+ /* Bus Mastering Base Address */
+ case 0x20 ... 0x21:
+ if (addr == 0x20)
+ dev->pci_conf[addr] = (val & 0xe0) | 0x01;
+ else if ((addr & 0x07) == 0x00)
+ dev->pci_conf[addr] = (val & 0xf8) | 0x01;
+ else if ((addr & 0x07) == 0x04)
+ dev->pci_conf[addr] = (val & 0xfc) | 0x01;
+ else
+ dev->pci_conf[addr] = val;
+ sis_5513_ide_handler(dev);
+ break;
+
+ case 0x2c ... 0x2f:
+ if (dev->rev >= 0xd0)
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x30 ... 0x33: /* Expansion ROM Base Address */
+#ifdef DATASHEET
+ dev->pci_conf[addr] = val;
+#else
+ if (dev->rev == 0x00)
+ dev->pci_conf[addr] = val;
+#endif
+ break;
+
+ case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
+ if (dev->rev >= 0xd0)
+ dev->pci_conf[addr] = val & 0xcf;
+ else
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
+ case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
+ case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
+ case 0x48: /* IDE Command Recovery Time Control */
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
+ case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
+ case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
+ case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
+ if (dev->rev >= 0xd0)
+ dev->pci_conf[addr] = val & 0xe7;
+ else
+ dev->pci_conf[addr] = val & 0x07;
+ break;
+
+ case 0x49: /* IDE Command Active Time Control */
+ dev->pci_conf[addr] = val & 0x07;
+ break;
+
+ case 0x4a: /* IDE General Control Register 0 */
+ switch (dev->rev) {
+ case 0x00:
+ dev->pci_conf[addr] = val & 0x9e;
+ break;
+ case 0xc0:
+ dev->pci_conf[addr] = val & 0xaf;
+ break;
+ case 0xd0:
+ dev->pci_conf[addr] = val;
+ break;
+ }
+ sis_5513_ide_handler(dev);
+ break;
+
+ case 0x4b: /* IDE General Control Register 1 */
+ if (dev->rev >= 0xc0)
+ dev->pci_conf[addr] = val;
+ else
+ dev->pci_conf[addr] = val & 0xef;
+ break;
+
+ case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
+ case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
+ case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
+ case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x50:
+ case 0x51:
+ if (dev->rev >= 0xd0)
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x52:
+ if (dev->rev >= 0xd0)
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ default:
+ break;
+ }
+}
+
+uint8_t
+sis_5513_ide_read(int addr, void *priv)
+{
+ const sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
+ uint8_t ret = 0xff;
+
+ switch (addr) {
+ default:
+ ret = dev->pci_conf[addr];
+ break;
+ case 0x09:
+ ret = dev->pci_conf[addr];
+ if (dev->rev >= 0xc0) {
+ if (dev->pci_conf[0x09] & 0x40)
+ ret |= ((dev->pci_conf[0x4a] & 0x06) << 3);
+ if ((dev->rev == 0xd0) && dev->sis->ide_bits_1_3_writable)
+ ret |= 0x0a;
+ }
+ break;
+ case 0x3d:
+ if (dev->rev >= 0xc0)
+ ret = (dev->pci_conf[0x09] & 0x05) ? PCI_INTA : 0x00;
+ else
+ ret = (((dev->pci_conf[0x4b] & 0xc0) == 0xc0) ||
+ (dev->pci_conf[0x09] & 0x05)) ? PCI_INTA : 0x00;
+ break;
+ }
+
+ sis_5513_ide_log("SiS 5513 IDE: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5513_ide_reset(void *priv)
+{
+ sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x13;
+ dev->pci_conf[0x03] = 0x55;
+ dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00;
+ dev->pci_conf[0x06] = dev->pci_conf[0x07] = 0x00;
+ dev->pci_conf[0x08] = (dev->rev == 0xd1) ? 0xd0 : dev->rev;
+ dev->pci_conf[0x09] = 0x8a;
+ dev->pci_conf[0x0a] = dev->pci_conf[0x0b] = 0x01;
+ dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00;
+ dev->pci_conf[0x0e] = 0x80;
+ dev->pci_conf[0x0f] = 0x00;
+ dev->pci_conf[0x10] = 0xf1;
+ dev->pci_conf[0x11] = 0x01;
+ dev->pci_conf[0x14] = 0xf5;
+ dev->pci_conf[0x15] = 0x03;
+ dev->pci_conf[0x18] = 0x71;
+ dev->pci_conf[0x19] = 0x01;
+ dev->pci_conf[0x1c] = 0x75;
+ dev->pci_conf[0x1d] = 0x03;
+ dev->pci_conf[0x20] = 0x01;
+ dev->pci_conf[0x21] = 0xf0;
+ dev->pci_conf[0x22] = dev->pci_conf[0x23] = 0x00;
+ dev->pci_conf[0x24] = dev->pci_conf[0x25] = 0x00;
+ dev->pci_conf[0x26] = dev->pci_conf[0x27] = 0x00;
+ dev->pci_conf[0x28] = dev->pci_conf[0x29] = 0x00;
+ dev->pci_conf[0x2a] = dev->pci_conf[0x2b] = 0x00;
+ switch (dev->rev) {
+ case 0x00:
+ case 0xd0:
+ case 0xd1:
+ dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00;
+ break;
+ case 0xc0:
+#ifdef DATASHEET
+ dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00;
+#else
+ /* The only Linux lspci listing I could find of this chipset,
+ shows a subsystem of 0058:0000. */
+ dev->pci_conf[0x2c] = 0x58;
+ dev->pci_conf[0x2d] = 0x00;
+#endif
+ break;
+ }
+ dev->pci_conf[0x2e] = dev->pci_conf[0x2f] = 0x00;
+ dev->pci_conf[0x30] = dev->pci_conf[0x31] = 0x00;
+ dev->pci_conf[0x32] = dev->pci_conf[0x33] = 0x00;
+ dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00;
+ dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00;
+ dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00;
+ dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00;
+ dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00;
+ dev->pci_conf[0x4a] = 0x06;
+ dev->pci_conf[0x4b] = 0x00;
+ dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00;
+ dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00;
+
+ sis_5513_ide_irq_handler(dev);
+ sis_5513_ide_handler(dev);
+
+ sff_bus_master_reset(dev->sis->bm[0]);
+ sff_bus_master_reset(dev->sis->bm[1]);
+}
+
+static void
+sis_5513_ide_close(void *priv)
+{
+ sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_5513_ide_init(UNUSED(const device_t *info))
+{
+ sis_5513_ide_t *dev = (sis_5513_ide_t *) calloc(1, sizeof(sis_5513_ide_t));
+
+ dev->rev = info->local;
+
+ dev->sis = device_get_common_priv();
+
+ /* SFF IDE */
+ dev->sis->bm[0] = device_add_inst(&sff8038i_device, 1);
+ dev->sis->bm[1] = device_add_inst(&sff8038i_device, 2);
+
+ sis_5513_ide_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5513_ide_device = {
+ .name = "SiS 5513 IDE controller",
+ .internal_name = "sis_5513_ide",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5513_ide_init,
+ .close = sis_5513_ide_close,
+ .reset = sis_5513_ide_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5572_ide_device = {
+ .name = "SiS 5572 IDE controller",
+ .internal_name = "sis_5572_ide",
+ .flags = DEVICE_PCI,
+ .local = 0xc0,
+ .init = sis_5513_ide_init,
+ .close = sis_5513_ide_close,
+ .reset = sis_5513_ide_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5582_ide_device = {
+ .name = "SiS 5582 IDE controller",
+ .internal_name = "sis_5582_ide",
+ .flags = DEVICE_PCI,
+ .local = 0xd0,
+ .init = sis_5513_ide_init,
+ .close = sis_5513_ide_close,
+ .reset = sis_5513_ide_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5591_5600_ide_device = {
+ .name = "SiS 5591/(5)600 IDE controller",
+ .internal_name = "sis_5591_5600_ide",
+ .flags = DEVICE_PCI,
+ .local = 0xd1, /* D0, but we need to distinguish them. */
+ .init = sis_5513_ide_init,
+ .close = sis_5513_ide_close,
+ .reset = sis_5513_ide_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5513_p2i.c b/src/chipset/sis_5513_p2i.c
new file mode 100644
index 0000000000..ef9a6746dd
--- /dev/null
+++ b/src/chipset/sis_5513_p2i.c
@@ -0,0 +1,1383 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5513 PCI to ISA bridge.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+
+#ifdef ENABLE_SIS_5513_PCI_TO_ISA_LOG
+int sis_5513_pci_to_isa_do_log = ENABLE_SIS_5513_PCI_TO_ISA_LOG;
+
+static void
+sis_5513_pci_to_isa_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5513_pci_to_isa_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5513_pci_to_isa_log(fmt, ...)
+#endif
+
+typedef struct sis_5513_pci_to_isa_t {
+ uint8_t rev;
+ uint8_t index;
+ uint8_t dam_index;
+ uint8_t irq_state;
+ uint8_t dam_enable;
+ uint8_t dam_irq_enable;
+ uint8_t ddma_enable;
+ uint8_t pci_conf[256];
+ uint8_t regs[16];
+ uint8_t dam_regs[256];
+ uint8_t apc_regs[256];
+
+ uint16_t dam_base;
+ uint16_t ddma_base;
+ uint16_t acpi_io_base;
+
+ sis_55xx_common_t *sis;
+ port_92_t *port_92;
+ void *pit;
+ nvr_t *nvr;
+ char *fn;
+ ddma_t *ddma;
+ acpi_t *acpi;
+ void *smbus;
+
+ uint8_t (*pit_read_reg)(void *priv, uint8_t reg);
+} sis_5513_pci_to_isa_t;
+
+static void
+sis_5595_acpi_recalc(sis_5513_pci_to_isa_t *dev)
+{
+ dev->acpi_io_base = (dev->pci_conf[0x91] << 8) | (dev->pci_conf[0x90] & 0xc0);
+ acpi_update_io_mapping(dev->sis->acpi, dev->acpi_io_base, (dev->pci_conf[0x40] & 0x80));
+}
+
+static void
+sis_5513_apc_reset(sis_5513_pci_to_isa_t *dev)
+{
+ memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs));
+
+ if (dev->rev == 0b0) {
+ dev->apc_regs[0x03] = 0x80;
+ dev->apc_regs[0x04] = 0x38;
+ dev->apc_regs[0x07] = 0x01;
+ } else
+ dev->apc_regs[0x04] = 0x08;
+}
+
+static void
+sis_5513_apc_write(uint16_t addr, uint8_t val, void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ uint8_t nvr_index = nvr_get_index(dev->nvr, 0);
+
+ sis_5513_pci_to_isa_log("SiS 5595 APC: [W] %04X = %02X\n", addr, val);
+
+ switch (nvr_index) {
+ case 0x02 ... 0x04:
+ dev->apc_regs[nvr_index] = val;
+ break;
+ case 0x05:
+ case 0x07 ... 0x08:
+ if (dev->rev == 0xb0)
+ dev->apc_regs[nvr_index] = val;
+ break;
+ }
+}
+
+static uint8_t
+sis_5513_apc_read(uint16_t addr, void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ uint8_t nvr_index = nvr_get_index(dev->nvr, 0);
+ uint8_t ret = 0xff;
+
+ ret = dev->apc_regs[nvr_index];
+
+ if (nvr_index == 0x06)
+ dev->apc_regs[nvr_index] = 0x00;
+
+ sis_5513_pci_to_isa_log("SiS 5595 APC: [R] %04X = %02X\n", addr, ret);
+
+ return ret;
+}
+
+void
+sis_5513_apc_recalc(sis_5513_pci_to_isa_t *dev, uint8_t apc_on)
+{
+ nvr_at_data_port(!apc_on, dev->nvr);
+ io_removehandler(0x0071, 0x0001,
+ sis_5513_apc_read, NULL, NULL, sis_5513_apc_write, NULL, NULL, dev);
+
+ if (apc_on)
+ io_removehandler(0x0071, 0x0001,
+ sis_5513_apc_read, NULL, NULL, sis_5513_apc_write, NULL, NULL, dev);
+}
+
+static void
+sis_5595_do_nmi(sis_5513_pci_to_isa_t *dev, int set)
+{
+ if (set)
+ nmi_raise();
+
+ dev->irq_state = set;
+}
+
+static void
+sis_5595_dam_reset(sis_5513_pci_to_isa_t *dev)
+{
+ if (dev->irq_state) {
+ if (dev->dam_regs[0x40] & 0x20)
+ sis_5595_do_nmi(dev, 0);
+ else if (dev->dam_irq_enable)
+ pci_clear_mirq(6, 1, &dev->irq_state);
+ }
+
+ memset(dev->dam_regs, 0x00, sizeof(dev->dam_regs));
+
+ dev->dam_regs[0x40] = 0x08;
+ dev->dam_regs[0x47] = 0x50;
+}
+
+static void
+sis_5595_dam_write(uint16_t addr, uint8_t val, void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ uint16_t reg = addr - dev->dam_base;
+ uint8_t old;
+
+ sis_5513_pci_to_isa_log("SiS 5595 DAM: [W] %04X = %02X\n", addr, val);
+
+ switch (reg) {
+ case 0x05:
+ dev->dam_index = (dev->index & 0x80) | (val & 0x7f);
+ break;
+ case 0x06:
+ switch (dev->dam_index) {
+ case 0x40:
+ old = dev->dam_regs[0x40];
+ dev->dam_regs[0x40] = val & 0xef;
+ if (val & 0x80) {
+ sis_5595_dam_reset(dev);
+ return;
+ }
+ if (dev->irq_state) {
+ if (!(old & 0x20) && (val & 0x20)) {
+ if (dev->dam_irq_enable)
+ pci_clear_mirq(6, 1, &dev->irq_state);
+ sis_5595_do_nmi(dev, 1);
+ } else if ((old & 0x20) && !(val & 0x20)) {
+ sis_5595_do_nmi(dev, 0);
+ if (dev->dam_irq_enable)
+ pci_set_mirq(6, 1, &dev->irq_state);
+ }
+ }
+ if ((val & 0x08) && dev->dam_irq_enable)
+ pci_clear_mirq(6, 1, &dev->irq_state);
+ break;
+ case 0x43 ... 0x47:
+ dev->dam_regs[dev->dam_index] = val;
+ break;
+ case 0x2b ... 0x34:
+ case 0x6b ... 0x74:
+ case 0x3b ... 0x3c:
+ case 0x7b ... 0x7c:
+ dev->dam_regs[dev->dam_index & 0x3f] = val;
+ break;
+ }
+ break;
+ }
+}
+
+static uint8_t
+sis_5595_dam_read(uint16_t addr, void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ uint16_t reg = addr - dev->dam_base;
+ uint8_t ret = 0xff;
+
+ switch (reg) {
+ case 0x05:
+ ret = dev->dam_index;
+ break;
+ case 0x06:
+ switch (dev->dam_index) {
+ default:
+ ret = dev->dam_regs[dev->dam_index];
+ break;
+ case 0x20 ... 0x29:
+ case 0x2b ... 0x3f:
+ ret = dev->dam_regs[dev->dam_index & 0x3f];
+ break;
+ case 0x2a:
+ case 0x6a:
+ ret = dev->pci_conf[0x78];
+ break;
+ }
+ break;
+ }
+
+ sis_5513_pci_to_isa_log("SiS 5595 DAM: [R] %04X = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5595_dam_recalc(sis_5513_pci_to_isa_t *dev)
+{
+ if (dev->dam_enable && (dev->dam_base != 0x0000))
+ io_removehandler(dev->dam_base, 0x0008,
+ sis_5595_dam_read, NULL, NULL, sis_5595_dam_write, NULL, NULL, dev);
+
+ dev->dam_base = dev->pci_conf[0x68] | (dev->pci_conf[0x69] << 16);
+ dev->dam_enable = !!(dev->pci_conf[0x7b] & 0x80);
+
+ if (dev->dam_enable && (dev->dam_base != 0x0000))
+ io_sethandler(dev->dam_base, 0x0008,
+ sis_5595_dam_read, NULL, NULL, sis_5595_dam_write, NULL, NULL, dev);
+}
+
+static void
+sis_5595_ddma_recalc(sis_5513_pci_to_isa_t *dev)
+{
+ uint16_t ch_base;
+
+ dev->ddma_base = (dev->pci_conf[0x80] & 0xf0) | (dev->pci_conf[0x81] << 16);
+ dev->ddma_enable = !!(dev->pci_conf[0x80] & 0x01);
+
+ for (uint8_t i = 0; i < 8; i++) {
+ ch_base = dev->ddma_base + (i << 4);
+ ddma_update_io_mapping(dev->ddma, i, ch_base & 0xff, (ch_base >> 8),
+ dev->ddma_enable && (dev->pci_conf[0x84] & (1 << i)) &&
+ (dev->ddma_base != 0x0000));
+ }
+}
+
+static void
+sis_5513_00_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev)
+{
+ switch (addr) {
+ case 0x60: /* MIRQ0 Remapping Control Register */
+ case 0x61: /* MIRQ1 Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val);
+ dev->pci_conf[addr] = val & 0xcf;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
+ break;
+
+ case 0x62: /* On-board Device DMA Control Register */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x63: /* IDEIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val & 0x8f;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
+ break;
+
+ case 0x64: /* GPIO0 Control Register */
+ dev->pci_conf[addr] = val & 0xef;
+ break;
+
+ case 0x65:
+ dev->pci_conf[addr] = val & 0x80;
+ break;
+
+ case 0x66: /* GPIO0 Output Mode Control Register */
+ case 0x67: /* GPIO0 Output Mode Control Register */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6a: /* GPIO Status Register */
+ dev->pci_conf[addr] |= (val & 0x10);
+ dev->pci_conf[addr] &= ~(val & 0x01);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+sis_5513_01_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev)
+{
+ uint8_t old;
+
+ switch (addr) {
+ /* Simply skip MIRQ0, so we can reuse the SiS 551x IDEIRQ infrastructure. */
+ case 0x61: /* MIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val);
+ dev->pci_conf[addr] = val & 0xcf;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
+ break;
+
+ case 0x62: /* On-board Device DMA Control Register */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x63: /* IDEIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val & 0x8f;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
+ break;
+
+ case 0x64: /* GPIO Control Register */
+ dev->pci_conf[addr] = val & 0xef;
+ break;
+
+ case 0x65:
+ dev->pci_conf[addr] = val & 0x1b;
+ break;
+
+ case 0x66: /* GPIO Output Mode Control Register */
+ case 0x67: /* GPIO Output Mode Control Register */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x68: /* USBIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val & 0xcf;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ3, val & 0xf);
+ break;
+
+ case 0x69:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6a:
+ dev->pci_conf[addr] = val & 0xfc;
+ break;
+
+ case 0x6b:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6c:
+ dev->pci_conf[addr] = val & 0x02;
+ break;
+
+ case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */
+ old = dev->pci_conf[addr];
+ picint((val ^ old) & val);
+ picintc((val ^ old) & ~val);
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */
+ old = dev->pci_conf[addr];
+ picint(((val ^ old) & val) << 8);
+ picintc(((val ^ old) & ~val) << 8);
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x70:
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x02) | (val & 0xdc);
+ break;
+
+ case 0x71: /* Type-F DMA Control Register */
+ dev->pci_conf[addr] = val & 0xef;
+ break;
+
+ case 0x72: /* SMI Triggered By IRQ/GPIO Control */
+ case 0x73: /* SMI Triggered By IRQ/GPIO Control */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x74: /* System Standby Timer Reload,
+ System Standby State Exit And Throttling State Exit Control */
+ case 0x75: /* System Standby Timer Reload,
+ System Standby State Exit And Throttling State Exit Control */
+ case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
+ case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
+ dev->pci_conf[addr] = val;
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+sis_5513_11_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev)
+{
+ uint8_t old;
+
+ switch (addr) {
+ case 0x61: /* IDEIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val & 0xcf;
+ dev->sis->ide_bits_1_3_writable = !!(val & 0x40);
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
+ break;
+
+ case 0x62: /* USBIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val;
+ dev->sis->usb_enabled = !!(val & 0x40);
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ3, val & 0xf);
+ break;
+
+ case 0x63: /* GPCS0 Control Register */
+ case 0x64: /* GPCS1 Control Register */
+ case 0x65: /* GPCS0 Output Mode Control Register */
+ case 0x66: /* GPCS0 Output Mode Control Register */
+ case 0x67: /* GPCS1 Output Mode Control Register */
+ case 0x68: /* GPCS1 Output Mode Control Register */
+ case 0x6b:
+ case 0x6c:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x69: /* GPCS0/1 De-Bounce Control Register */
+ dev->pci_conf[addr] = val & 0xdf;
+ if ((dev->apc_regs[0x03] & 0x40) && (val & 0x10)) {
+ plat_power_off();
+ return;
+ }
+ break;
+
+ case 0x6a: /* ACPI/SCI IRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: ACPI/SCI IRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ5, val & 0xf);
+ break;
+
+ case 0x6d: /* I2C Bus Control Register */
+ dev->pci_conf[addr] = val;
+ /* TODO: Keyboard/mouse swapping and keyboard hot key. */
+ break;
+
+ case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */
+ old = dev->pci_conf[addr];
+ picint((val ^ old) & val);
+ picintc((val ^ old) & ~val);
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */
+ old = dev->pci_conf[addr];
+ picint(((val ^ old) & val) << 8);
+ picintc(((val ^ old) & ~val) << 8);
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x70: /* Misc. Controller Register */
+ dev->pci_conf[addr] = val;
+ /* TODO: Keyboard Lock Enable/Disable. */
+ break;
+
+ case 0x71: /* Type F DMA Control Register */
+ dev->pci_conf[addr] = val & 0xef;
+ break;
+
+ case 0x72: /* SMI Triggered By IRQ Control */
+ dev->pci_conf[addr] = val & 0xfa;
+ break;
+ case 0x73: /* SMI Triggered By IRQ Control */
+ case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit */
+ case 0x77: /* Monoitor Standby Timer Reload And Monoitor Standby State Exit Control */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit */
+ case 0x76: /* Monoitor Standby Timer Reload And Monoitor Standby State Exit Control */
+ dev->pci_conf[addr] = val & 0xfb;
+ break;
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x80: /* Distributed DMA Master Configuration Register */
+ case 0x81: /* Distributed DMA Master Configuration Register */
+ dev->pci_conf[addr] = val;
+ sis_5595_ddma_recalc(dev);
+ break;
+
+ case 0x84: /* Individual Distributed DMA Channel Enable */
+ dev->pci_conf[addr] = val;
+ sis_5595_ddma_recalc(dev);
+ break;
+
+ case 0x88: /* Serial Interrupt Control Register */
+ case 0x89: /* Serial Interrupt Enable Register 1 */
+ case 0x8a: /* Serial Interrupt Enable Register 2 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x90: /* ACPI Base Address Register */
+ dev->pci_conf[addr] = val & 0xc0;
+ sis_5595_acpi_recalc(dev);
+ break;
+ case 0x91: /* ACPI Base Address Register */
+ dev->pci_conf[addr] = val;
+ sis_5595_acpi_recalc(dev);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+sis_5513_b0_pci_to_isa_write(int addr, uint8_t val, sis_5513_pci_to_isa_t *dev)
+{
+ uint8_t old;
+
+ switch (addr) {
+ case 0x61: /* IDEIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val & 0xdf;
+ sff_set_mirq(dev->sis->bm[0], (val & 0x10) ? 7 : 2);
+ sff_set_mirq(dev->sis->bm[1], (val & 0x10) ? 2 : 7);
+ pci_set_mirq_routing(PCI_MIRQ7, 14 + (!!(val & 0x10)));
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
+ break;
+
+ case 0x62: /* USBIRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: USBIRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val;
+ dev->sis->usb_enabled = !!(val & 0x40);
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ3, val & 0xf);
+ break;
+
+ case 0x63: /* PCI OutputBuffer Current Strength Register */
+ dev->pci_conf[addr] = val;
+ if ((dev->apc_regs[0x03] & 0x40) && (val & 0x04)) {
+ plat_power_off();
+ return;
+ }
+ if ((val & 0x18) == 0x18) {
+ dma_reset();
+ dma_set_at(1);
+
+ device_reset_all(DEVICE_ALL);
+
+ cpu_alt_reset = 0;
+
+ pci_reset();
+
+ mem_a20_alt = 0;
+ mem_a20_recalc();
+
+ flushmmucache();
+
+ resetx86();
+ }
+ break;
+
+ case 0x64: /* INIT Enable Register */
+ dev->pci_conf[addr] = val;
+ cpu_cpurst_on_sr = !(val & 0x20);
+ break;
+
+ case 0x65: /* PHOLD# Timer */
+ case 0x66: /* Priority Timer */
+ case 0x67: /* Respond to C/D Segments Register */
+ case 0x6b: /* Test Mode Register I */
+ case 0x6c: /* Test Mode Register II */
+ case 0x71: /* Reserved */
+ case 0x72: /* Individual PC/PCI DMA Channel Enable */
+ case 0x7c: /* Data Acquisition Module ADC Calibration */
+ case 0x7d: /* Data Acquisition Module ADC Calibration */
+ case 0x88: /* Serial Interrupt Control Register */
+ case 0x89: /* Serial Interrupt Enable Register 1 */
+ case 0x8a: /* Serial Interrupt Enable Register 2 */
+ case 0x8c: /* Serial Interrupt Enable Register 3 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x68: /* Data Acquistion Module Base Address */
+ dev->pci_conf[addr] = val & 0xf8;
+ sis_5595_dam_recalc(dev);
+ break;
+
+ case 0x6a: /* ACPI/SCI IRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: ACPI/SCI IRQ -> %02X\n", val);
+ dev->pci_conf[addr] = val & 0x8f;
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ5, val & 0xf);
+ break;
+
+ case 0x6d: /* I2C Bus Control Register */
+ dev->pci_conf[addr] = val;
+ /* TODO: Keyboard/mouse swapping and keyboard hot key. */
+ break;
+
+ case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */
+ old = dev->pci_conf[addr];
+ picint((val ^ old) & val);
+ picintc((val ^ old) & ~val);
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */
+ old = dev->pci_conf[addr];
+ picint(((val ^ old) & val) << 8);
+ picintc(((val ^ old) & ~val) << 8);
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x70: /* Misc. Controller Register */
+ dev->pci_conf[addr] = val;
+ /* TODO: Keyboard Lock Enable/Disable. */
+ break;
+
+ case 0x73:
+ case 0x75 ... 0x79:
+ if (dev->rev == 0x81)
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x7a: /* Data Acquisition Module Function Selection Register */
+ if (dev->rev == 0x81)
+ dev->pci_conf[addr] = val;
+ else
+ dev->pci_conf[addr] = val & 0x90;
+ break;
+
+ case 0x7b: /* Data Acquisition Module Control Register */
+ dev->pci_conf[addr] = val;
+ sis_5595_dam_recalc(dev);
+ break;
+
+ case 0x7e: /* Data Acquisition Module and SMBUS IRQ Remapping Control Register */
+ sis_5513_pci_to_isa_log("Set MIRQ routing: DAM/SMBUS IRQ -> %02X\n", val);
+ if (dev->rev == 0x81)
+ dev->pci_conf[addr] = val & 0x8f;
+ else {
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x10) | (val & 0xef);
+
+ dev->dam_irq_enable = ((val & 0xc0) == 0x40);
+ smbus_sis5595_irq_enable(dev->smbus, (val & 0xa0) == 0x20);
+ }
+ if (val & 0x80)
+ pci_set_mirq_routing(PCI_MIRQ6, PCI_IRQ_DISABLED);
+ else
+ pci_set_mirq_routing(PCI_MIRQ6, val & 0xf);
+ break;
+
+ case 0x80: /* Distributed DMA Master Configuration Register */
+ case 0x81: /* Distributed DMA Master Configuration Register */
+ dev->pci_conf[addr] = val;
+ sis_5595_ddma_recalc(dev);
+ break;
+
+ case 0x84: /* Individual Distributed DMA Channel Enable */
+ dev->pci_conf[addr] = val;
+ sis_5595_ddma_recalc(dev);
+ break;
+
+ case 0x90: /* ACPI Base Address Register */
+ dev->pci_conf[addr] = val & 0xc0;
+ sis_5595_acpi_recalc(dev);
+ break;
+ case 0x91: /* ACPI Base Address Register */
+ dev->pci_conf[addr] = val;
+ sis_5595_acpi_recalc(dev);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void
+sis_5513_pci_to_isa_write(int addr, uint8_t val, void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+
+ sis_5513_pci_to_isa_log("SiS 5513 P2I: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ case 0x04: /* Command */
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ case 0x07: /* Status */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x30);
+ break;
+
+ case 0x0d: /* Master Latency Timer */
+ if (dev->rev >= 0x11)
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x40: /* BIOS Control Register */
+ if (dev->rev >= 0x11) {
+ dev->pci_conf[addr] = val;
+ sis_5595_acpi_recalc(dev);
+ } else
+ dev->pci_conf[addr] = val & 0x3f;
+ break;
+
+ case 0x41: /* INTA# Remapping Control Register */
+ case 0x42: /* INTB# Remapping Control Register */
+ case 0x43: /* INTC# Remapping Control Register */
+ dev->pci_conf[addr] = val & 0x8f;
+ pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f));
+ break;
+ case 0x44: /* INTD# Remapping Control Register */
+ if (dev->rev == 0x11) {
+ dev->pci_conf[addr] = val & 0xcf;
+ sis_5513_apc_recalc(dev, val & 0x10);
+ } else
+ dev->pci_conf[addr] = val & 0x8f;
+ pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f));
+ break;
+
+ case 0x45: /* ISA Bus Control Register I */
+ if (dev->rev >= 0x01) {
+ if (dev->rev == 0x01)
+ dev->pci_conf[addr] = val & 0xec;
+ else
+ dev->pci_conf[addr] = val;
+ switch (val >> 6) {
+ case 0:
+ cpu_set_isa_speed(7159091);
+ break;
+ case 1:
+ cpu_set_isa_pci_div(4);
+ break;
+ case 2:
+ cpu_set_isa_pci_div(3);
+ break;
+
+ default:
+ break;
+ }
+ nvr_bank_set(0, !!(val & 0x08), dev->nvr);
+ if (dev->rev == 0xb0)
+ sis_5513_apc_recalc(dev, val & 0x02);
+ }
+ break;
+ case 0x46: /* ISA Bus Control Register II */
+ if (dev->rev >= 0x11)
+ dev->pci_conf[addr] = val;
+ else if (dev->rev == 0x00)
+ dev->pci_conf[addr] = val & 0xec;
+ break;
+ case 0x47: /* DMA Clock and Wait State Control Register */
+ switch (dev->rev) {
+ case 0x01:
+ dev->pci_conf[addr] = val & 0x3e;
+ break;
+ case 0x11:
+ dev->pci_conf[addr] = val & 0x7f;
+ break;
+ case 0xb0:
+ dev->pci_conf[addr] = val & 0xfd;
+ break;
+ }
+ break;
+
+ case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
+ case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
+ case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
+ case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ default:
+ switch (dev->rev) {
+ case 0x00:
+ sis_5513_00_pci_to_isa_write(addr, val, priv);
+ break;
+ case 0x01:
+ sis_5513_01_pci_to_isa_write(addr, val, priv);
+ break;
+ case 0x11:
+ sis_5513_11_pci_to_isa_write(addr, val, priv);
+ break;
+ case 0x81:
+ case 0xb0:
+ sis_5513_b0_pci_to_isa_write(addr, val, priv);
+ break;
+ }
+ break;
+ }
+}
+
+uint8_t
+sis_5513_pci_to_isa_read(int addr, void *priv)
+{
+ const sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ uint8_t ret = 0xff;
+
+ switch (addr) {
+ default:
+ ret = dev->pci_conf[addr];
+ break;
+ case 0x4c ... 0x4f:
+ ret = pic_read_icw(0, addr & 0x03);
+ break;
+ case 0x50 ... 0x53:
+ ret = pic_read_icw(1, addr & 0x03);
+ break;
+ case 0x54 ... 0x55:
+ ret = pic_read_ocw(0, addr & 0x01);
+ break;
+ case 0x56 ... 0x57:
+ ret = pic_read_ocw(1, addr & 0x01);
+ break;
+ case 0x58 ... 0x5f:
+ ret = dev->pit_read_reg(dev->pit, addr & 0x07);
+ break;
+ case 0x60:
+ if (dev->rev >= 0x01)
+ ret = inb(0x0070);
+ else
+ ret = dev->pci_conf[addr];
+ break;
+ }
+
+ sis_5513_pci_to_isa_log("SiS 5513 P2I: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+
+ switch (addr) {
+ case 0x22:
+ dev->index = val - 0x50;
+ break;
+ case 0x23:
+ sis_5513_pci_to_isa_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val);
+
+ switch (dev->index) {
+ case 0x00:
+ dev->regs[dev->index] = val & 0xed;
+ switch (val >> 6) {
+ case 0:
+ cpu_set_isa_speed(7159091);
+ break;
+ case 1:
+ cpu_set_isa_pci_div(4);
+ break;
+ case 2:
+ cpu_set_isa_pci_div(3);
+ break;
+
+ default:
+ break;
+ }
+ nvr_bank_set(0, !!(val & 0x08), dev->nvr);
+ break;
+ case 0x01:
+ dev->regs[dev->index] = val & 0xf4;
+ break;
+ case 0x03:
+ dev->regs[dev->index] = val & 3;
+ break;
+ case 0x04: /* BIOS Register */
+ dev->regs[dev->index] = val;
+ break;
+ case 0x05:
+ dev->regs[dev->index] = val;
+ outb(0x70, val);
+ break;
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ dev->regs[dev->index] = val;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static uint8_t
+sis_5513_isa_read(uint16_t addr, void *priv)
+{
+ const sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ uint8_t ret = 0xff;
+
+ if (addr == 0x23) {
+ if (dev->index == 0x05)
+ ret = inb(0x70);
+ else
+ ret = dev->regs[dev->index];
+
+ sis_5513_pci_to_isa_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret);
+ }
+
+ return ret;
+}
+
+static void
+sis_5513_00_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev)
+{
+ dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x80;
+ dev->pci_conf[0x62] = 0x00;
+ dev->pci_conf[0x63] = 0x80;
+ dev->pci_conf[0x64] = 0x00;
+ dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
+ dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
+ dev->pci_conf[0x6a] = 0x04;
+
+ pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
+
+ dev->regs[0x00] = dev->regs[0x01] = 0x00;
+ dev->regs[0x03] = dev->regs[0x04] = 0x00;
+ dev->regs[0x05] = 0x00;
+ dev->regs[0x08] = dev->regs[0x09] = 0x00;
+ dev->regs[0x0a] = dev->regs[0x0b] = 0x00;
+}
+
+static void
+sis_5513_01_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev)
+{
+ dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00;
+ dev->pci_conf[0x47] = 0x00;
+
+ dev->pci_conf[0x61] = 0x80;
+ dev->pci_conf[0x62] = 0x00;
+ dev->pci_conf[0x63] = 0x80;
+ dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
+ dev->pci_conf[0x68] = 0x80;
+ dev->pci_conf[0x69] = dev->pci_conf[0x6a] = 0x00;
+ dev->pci_conf[0x6b] = 0x00;
+ dev->pci_conf[0x6c] = 0x02;
+ dev->pci_conf[0x6d] = 0x00;
+ dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00;
+ dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
+ dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
+ dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
+
+ pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
+}
+
+static void
+sis_5513_11_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev)
+{
+ dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00;
+ dev->pci_conf[0x47] = 0x00;
+
+ dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0x80;
+ dev->pci_conf[0x63] = dev->pci_conf[0x64] = 0x00;
+ dev->pci_conf[0x65] = dev->pci_conf[0x66] = 0x00;
+ dev->pci_conf[0x67] = dev->pci_conf[0x68] = 0x00;
+ dev->pci_conf[0x69] = 0x01;
+ dev->pci_conf[0x6a] = 0x80;
+ dev->pci_conf[0x6b] = 0x00;
+ dev->pci_conf[0x6c] = 0x20;
+ dev->pci_conf[0x6d] = 0x19;
+ dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00;
+ dev->pci_conf[0x70] = 0x12;
+ dev->pci_conf[0x71] = dev->pci_conf[0x72] = 0x00;
+ dev->pci_conf[0x73] = dev->pci_conf[0x74] = 0x00;
+ dev->pci_conf[0x75] = dev->pci_conf[0x76] = 0x00;
+ dev->pci_conf[0x77] = 0x00;
+ dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x84] = dev->pci_conf[0x88] = 0x00;
+ dev->pci_conf[0x89] = dev->pci_conf[0x8a] = 0x00;
+ dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
+
+ pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED);
+
+ picint_common(0xffff, 0, 0, NULL);
+
+ sis_5595_ddma_recalc(dev);
+ sis_5595_acpi_recalc(dev);
+
+ dev->sis->ide_bits_1_3_writable = 0;
+ dev->sis->usb_enabled = 0;
+
+ sis_5513_apc_recalc(dev, 0);
+}
+
+static void
+sis_5513_b0_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev)
+{
+ dev->pci_conf[0x45] = dev->pci_conf[0x46] = 0x00;
+ dev->pci_conf[0x47] = 0x00;
+
+ dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0x80;
+ dev->pci_conf[0x63] = dev->pci_conf[0x64] = 0x00;
+ dev->pci_conf[0x65] = 0x01;
+ dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
+ dev->pci_conf[0x68] = 0x90;
+ dev->pci_conf[0x69] = 0x02;
+ dev->pci_conf[0x6a] = 0x80;
+ dev->pci_conf[0x6b] = 0x00;
+ dev->pci_conf[0x6c] = 0x20;
+ dev->pci_conf[0x6d] = 0x19;
+ dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00;
+ dev->pci_conf[0x70] = 0x12;
+ dev->pci_conf[0x71] = dev->pci_conf[0x72] = 0x00;
+ dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
+ dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00;
+ dev->pci_conf[0x7e] = 0x80;
+ dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x84] = dev->pci_conf[0x88] = 0x00;
+ dev->pci_conf[0x89] = dev->pci_conf[0x8a] = 0x00;
+ dev->pci_conf[0x8b] = dev->pci_conf[0x8c] = 0x00;
+ dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
+
+ pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ5, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ6, PCI_IRQ_DISABLED);
+ pci_set_mirq_routing(PCI_MIRQ7, 15);
+
+ sff_set_mirq(dev->sis->bm[0], 2);
+ sff_set_mirq(dev->sis->bm[1], 7);
+
+ picint_common(0xffff, 0, 0, NULL);
+
+ sis_5595_ddma_recalc(dev);
+ sis_5595_acpi_recalc(dev);
+
+ /* SiS 5595 Data Acquisition Module */
+ sis_5595_dam_recalc(dev);
+ sis_5595_dam_reset(dev);
+
+ dev->dam_irq_enable = 0;
+
+ cpu_cpurst_on_sr = 1;
+
+ dev->sis->usb_enabled = 0;
+
+ sis_5513_apc_recalc(dev, 0);
+
+ if (dev->rev == 0x81)
+ dev->dam_irq_enable = 1;
+}
+
+static void
+sis_5513_pci_to_isa_reset(void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x08;
+ dev->pci_conf[0x03] = 0x00;
+ dev->pci_conf[0x04] = 0x07;
+ dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
+ dev->pci_conf[0x07] = 0x02;
+ if ((dev->rev == 0x11) || (dev->rev == 0x81))
+ dev->pci_conf[0x08] = 0x01;
+ else
+ dev->pci_conf[0x08] = dev->rev;
+ dev->pci_conf[0x09] = 0x00;
+ dev->pci_conf[0x0a] = 0x01;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x0e] = 0x80;
+ dev->pci_conf[0x40] = 0x00;
+ dev->pci_conf[0x41] = dev->pci_conf[0x42] = 0x80;
+ dev->pci_conf[0x43] = dev->pci_conf[0x44] = 0x80;
+ dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00;
+ dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00;
+
+ switch (dev->rev) {
+ case 0x00:
+ sis_5513_00_pci_to_isa_reset(dev);
+ break;
+ case 0x01:
+ sis_5513_01_pci_to_isa_reset(dev);
+ break;
+ case 0x11:
+ sis_5513_11_pci_to_isa_reset(dev);
+ break;
+ case 0x81:
+ case 0xb0:
+ sis_5513_b0_pci_to_isa_reset(dev);
+ break;
+ }
+
+ pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
+ pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
+
+ pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
+
+ cpu_set_isa_speed(7159091);
+ nvr_bank_set(0, 0, dev->nvr);
+}
+
+static void
+sis_5513_pci_to_isa_close(void *priv)
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) priv;
+ FILE *fp = NULL;
+
+ if (dev->fn != NULL)
+ fp = nvr_fopen(dev->fn, "wb");
+
+ if (fp != NULL) {
+ (void) fwrite(dev->apc_regs, 256, 1, fp);
+ fclose(fp);
+ }
+
+ if (dev->fn != NULL)
+ free(dev->fn);
+
+ free(dev);
+}
+
+static void *
+sis_5513_pci_to_isa_init(UNUSED(const device_t *info))
+{
+ sis_5513_pci_to_isa_t *dev = (sis_5513_pci_to_isa_t *) calloc(1, sizeof(sis_5513_pci_to_isa_t));
+ uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
+ FILE *fp = NULL;
+ int c;
+
+ dev->rev = info->local;
+
+ dev->sis = device_get_common_priv();
+
+ /* IDEIRQ */
+ pci_enable_mirq(2);
+
+ /* Port 92h */
+ dev->port_92 = device_add(&port_92_device);
+
+ /* PIT */
+ dev->pit = device_find_first_priv(DEVICE_PIT);
+ dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg;
+
+ /* NVR */
+ dev->nvr = device_add(&at_mb_nvr_device);
+
+ switch (dev->rev) {
+ case 0x00:
+ /* MIRQ */
+ pci_enable_mirq(0);
+ pci_enable_mirq(1);
+
+ /* Ports 22h-23h: SiS 5513 ISA */
+ io_sethandler(0x0022, 0x0002,
+ sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev);
+ break;
+ case 0x01:
+ /* MIRQ */
+ pci_enable_mirq(1);
+ break;
+ case 0x11:
+ case 0x81:
+ case 0xb0:
+ /* USBIRQ */
+ pci_enable_mirq(3);
+
+ /* ACPI/SCI IRQ */
+ pci_enable_mirq(5);
+
+ if (dev->rev == 0xb0) {
+ /* Data Acquisition Module and SMBUS IRQ */
+ pci_enable_mirq(6);
+
+ /* Non-remapped native IDE IRQ */
+ pci_enable_mirq(7);
+ }
+
+ dev->ddma = device_add(&ddma_device);
+
+ switch (dev->rev) {
+ case 0x11:
+ dev->sis->acpi = device_add(&acpi_sis_5582_device);
+ break;
+ case 0x81:
+ dev->sis->acpi = device_add(&acpi_sis_5595_1997_device);
+ break;
+ case 0xb0:
+ dev->sis->acpi = device_add(&acpi_sis_5595_device);
+ dev->smbus = acpi_get_smbus(dev->sis->acpi);
+ break;
+ }
+
+ dev->sis->acpi->priv = dev->sis;
+ acpi_set_slot(dev->sis->acpi, dev->sis->sb_pci_slot);
+ acpi_set_nvr(dev->sis->acpi, dev->nvr);
+
+ /* Set up the NVR file's name. */
+ c = strlen(machine_get_internal_name()) + 9;
+ dev->fn = (char *) malloc(c + 1);
+ sprintf(dev->fn, "%s_apc.nvr", machine_get_internal_name());
+
+ fp = nvr_fopen(dev->fn, "rb");
+
+ memset(dev->apc_regs, 0x00, sizeof(dev->apc_regs));
+ sis_5513_apc_reset(dev);
+ if (fp != NULL) {
+ if (fread(dev->apc_regs, 1, 256, fp) != 256)
+ fatal("sis_5513_pci_to_isa_init(): Error reading APC data\n");
+ fclose(fp);
+ }
+
+ acpi_set_irq_mode(dev->sis->acpi, 2);
+ break;
+ }
+
+ sis_5513_pci_to_isa_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5513_p2i_device = {
+ .name = "SiS 5513 PCI to ISA bridge",
+ .internal_name = "sis_5513_pci_to_isa",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5513_pci_to_isa_init,
+ .close = sis_5513_pci_to_isa_close,
+ .reset = sis_5513_pci_to_isa_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5572_p2i_device = {
+ .name = "SiS 5572 PCI to ISA bridge",
+ .internal_name = "sis_5572_pci_to_isa",
+ .flags = DEVICE_PCI,
+ .local = 0x01,
+ .init = sis_5513_pci_to_isa_init,
+ .close = sis_5513_pci_to_isa_close,
+ .reset = sis_5513_pci_to_isa_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5582_p2i_device = {
+ .name = "SiS 5582 PCI to ISA bridge",
+ .internal_name = "sis_5582_pci_to_isa",
+ .flags = DEVICE_PCI,
+ .local = 0x11, /* Actually, 0x01, but we need to somehow distinguish it
+ from SiS 5572 and SiS 5595 1997, which are also revision 0x01. */
+ .init = sis_5513_pci_to_isa_init,
+ .close = sis_5513_pci_to_isa_close,
+ .reset = sis_5513_pci_to_isa_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5595_1997_p2i_device = {
+ .name = "SiS 5595 (1997) PCI to ISA bridge",
+ .internal_name = "sis_5595_1997_pci_to_isa",
+ .flags = DEVICE_PCI,
+ .local = 0x81, /* Actually, 0x01, but we need to somehow distinguish it
+ from SiS 5572 and SiS 5582, which are also revision 0x01. */
+ .init = sis_5513_pci_to_isa_init,
+ .close = sis_5513_pci_to_isa_close,
+ .reset = sis_5513_pci_to_isa_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5595_p2i_device = {
+ .name = "SiS 5595 PCI to ISA bridge",
+ .internal_name = "sis_5595_pci_to_isa",
+ .flags = DEVICE_PCI,
+ .local = 0xb0,
+ .init = sis_5513_pci_to_isa_init,
+ .close = sis_5513_pci_to_isa_close,
+ .reset = sis_5513_pci_to_isa_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c
index 007a961782..3fb1119785 100644
--- a/src/chipset/sis_5571.c
+++ b/src/chipset/sis_5571.c
@@ -6,11 +6,11 @@
*
* This file is part of the 86Box distribution.
*
- * Implementation of the SiS 5571 Pentium PCI/ISA Chipset.
+ * Implementation of the SiS 5571/5572 Pentium PCI/ISA Chipset.
*
* Authors: Miran Grca,
*
- * Copyright 2023-2024 Miran Grca.
+ * Copyright 2021-2023 Miran Grca.
*/
#include
#include
@@ -23,10 +23,10 @@
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
-
-// #include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
+#include <86box/apm.h>
+#include <86box/acpi.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -40,8 +40,7 @@
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
-#include <86box/usb.h>
-
+#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5571_LOG
@@ -63,1120 +62,83 @@ sis_5571_log(const char *fmt, ...)
#endif
typedef struct sis_5571_t {
- uint8_t index;
- uint8_t nb_slot;
- uint8_t sb_slot;
- uint8_t pad;
-
- uint8_t regs[16];
- uint8_t states[7];
- uint8_t pad0;
-
- uint8_t usb_unk_regs[8];
-
- uint8_t pci_conf[256];
- uint8_t pci_conf_sb[3][256];
-
- uint16_t usb_unk_base;
+ uint8_t nb_slot;
+ uint8_t sb_slot;
- sff8038i_t *bm[2];
- smram_t *smram;
- port_92_t *port_92;
- void *pit;
- nvr_t *nvr;
- usb_t *usb;
+ void *h2p;
+ void *p2i;
+ void *ide;
+ void *usb;
- uint8_t (*pit_read_reg)(void *priv, uint8_t reg);
+ sis_55xx_common_t *sis;
} sis_5571_t;
static void
-sis_5571_shadow_recalc(sis_5571_t *dev)
-{
- int state;
- uint32_t base;
-
- for (uint8_t i = 0x70; i <= 0x76; i++) {
- if (i == 0x76) {
- if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
- state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
- mem_set_mem_state_both(0xf0000, 0x10000, state);
- sis_5571_log("000F0000-000FFFFF\n");
- }
- } else {
- base = ((i & 0x07) << 15) + 0xc0000;
-
- if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
- state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
- mem_set_mem_state_both(base, 0x4000, state);
- sis_5571_log("%08X-%08X\n", base, base + 0x3fff);
- }
-
- if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
- state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
- state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
- mem_set_mem_state_both(base + 0x4000, 0x4000, state);
- sis_5571_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
- }
- }
-
- dev->states[i & 0x0f] = dev->pci_conf[i];
- }
-
- flushmmucache_nopc();
-}
-
-static void
-sis_5571_smram_recalc(sis_5571_t *dev)
-{
- smram_disable_all();
-
- switch (dev->pci_conf[0xa3] >> 6) {
- case 0:
- smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
- break;
- case 1:
- smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
- break;
- case 2:
- smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
- break;
- case 3:
- smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1);
- break;
-
- default:
- break;
- }
-
- flushmmucache();
-}
-
-static void
-sis_5571_mem_to_pci_reset(sis_5571_t *dev)
-{
- dev->pci_conf[0x00] = 0x39;
- dev->pci_conf[0x01] = 0x10;
- dev->pci_conf[0x02] = 0x71;
- dev->pci_conf[0x03] = 0x55;
- dev->pci_conf[0x04] = 0x05;
- dev->pci_conf[0x05] = 0x00;
- dev->pci_conf[0x06] = 0x00;
- dev->pci_conf[0x07] = 0x02;
- dev->pci_conf[0x08] = 0x00;
- dev->pci_conf[0x09] = 0x00;
- dev->pci_conf[0x0a] = 0x00;
- dev->pci_conf[0x0b] = 0x06;
- dev->pci_conf[0x0c] = 0x00;
- dev->pci_conf[0x0d] = 0x00;
- dev->pci_conf[0x0e] = 0x00;
- dev->pci_conf[0x0f] = 0x00;
-
- dev->pci_conf[0x50] = 0x00;
- dev->pci_conf[0x51] = 0x00;
- dev->pci_conf[0x52] = 0x00;
- dev->pci_conf[0x53] = 0x00;
- dev->pci_conf[0x54] = 0x54;
- dev->pci_conf[0x55] = 0x54;
- dev->pci_conf[0x56] = 0x03;
- dev->pci_conf[0x57] = 0x00;
- dev->pci_conf[0x58] = 0x00;
- dev->pci_conf[0x59] = 0x00;
- dev->pci_conf[0x5a] = 0x00;
-
- /* Undocumented DRAM bank registers. */
- dev->pci_conf[0x60] = dev->pci_conf[0x62] = 0x04;
- dev->pci_conf[0x64] = dev->pci_conf[0x66] = 0x04;
- dev->pci_conf[0x68] = dev->pci_conf[0x6a] = 0x04;
- dev->pci_conf[0x61] = dev->pci_conf[0x65] = 0x00;
- dev->pci_conf[0x63] = dev->pci_conf[0x67] = 0x80;
- dev->pci_conf[0x69] = 0x00;
- dev->pci_conf[0x6b] = 0x80;
-
- dev->pci_conf[0x70] = 0x00;
- dev->pci_conf[0x71] = 0x00;
- dev->pci_conf[0x72] = 0x00;
- dev->pci_conf[0x73] = 0x00;
- dev->pci_conf[0x74] = 0x00;
- dev->pci_conf[0x75] = 0x00;
- dev->pci_conf[0x76] = 0x00;
-
- dev->pci_conf[0x77] = 0x00;
- dev->pci_conf[0x78] = 0x00;
- dev->pci_conf[0x79] = 0x00;
- dev->pci_conf[0x7a] = 0x00;
- dev->pci_conf[0x7b] = 0x00;
-
- dev->pci_conf[0x80] = 0x00;
- dev->pci_conf[0x81] = 0x00;
- dev->pci_conf[0x82] = 0x00;
- dev->pci_conf[0x83] = 0x00;
- dev->pci_conf[0x84] = 0x00;
- dev->pci_conf[0x85] = 0x00;
- dev->pci_conf[0x86] = 0x00;
- dev->pci_conf[0x87] = 0x00;
-
- dev->pci_conf[0x8c] = 0x00;
- dev->pci_conf[0x8d] = 0x00;
- dev->pci_conf[0x8e] = 0x00;
- dev->pci_conf[0x8f] = 0x00;
-
- dev->pci_conf[0x90] = 0x00;
- dev->pci_conf[0x91] = 0x00;
- dev->pci_conf[0x92] = 0x00;
- dev->pci_conf[0x93] = 0x00;
- dev->pci_conf[0x93] = 0x00;
- dev->pci_conf[0x94] = 0x00;
- dev->pci_conf[0x95] = 0x00;
- dev->pci_conf[0x96] = 0x00;
- dev->pci_conf[0x97] = 0x00;
- dev->pci_conf[0x98] = 0x00;
- dev->pci_conf[0x99] = 0x00;
- dev->pci_conf[0x9a] = 0x00;
- dev->pci_conf[0x9b] = 0x00;
- dev->pci_conf[0x9c] = 0x00;
- dev->pci_conf[0x9d] = 0x00;
- dev->pci_conf[0x9e] = 0xff;
- dev->pci_conf[0x9f] = 0xff;
-
- dev->pci_conf[0xa0] = 0xff;
- dev->pci_conf[0xa1] = 0x00;
- dev->pci_conf[0xa2] = 0xff;
- dev->pci_conf[0xa3] = 0x00;
-
- cpu_cache_ext_enabled = 0;
- cpu_update_waitstates();
-
- sis_5571_smram_recalc(dev);
- sis_5571_shadow_recalc(dev);
-
- flushmmucache();
-}
-
-static void
-sis_5571_mem_to_pci_write(int func, int addr, uint8_t val, void *priv)
-{
- sis_5571_t *dev = (sis_5571_t *) priv;
-
- if (func == 0) {
- sis_5571_log("SiS 5571 M2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
-
- switch (addr) {
- case 0x04: /* Command - low byte */
- case 0x05: /* Command - high byte */
- dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
- break;
-
- case 0x07: /* Status - High Byte */
- dev->pci_conf[addr] &= ~(val & 0xb8);
- break;
-
- case 0x0d: /* Master latency timer */
- dev->pci_conf[addr] = val;
- break;
-
- case 0x50: /* Host Interface and DRAM arbiter */
- dev->pci_conf[addr] = val & 0xec;
- break;
-
- case 0x51: /* CACHE */
- dev->pci_conf[addr] = val;
- cpu_cache_ext_enabled = !!(val & 0x40);
- cpu_update_waitstates();
- break;
-
- case 0x52:
- dev->pci_conf[addr] = val & 0xd0;
- break;
-
- case 0x53: /* DRAM */
- dev->pci_conf[addr] = val & 0xfe;
- break;
-
- case 0x54: /* FP/EDO */
- dev->pci_conf[addr] = val;
- break;
-
- case 0x55:
- dev->pci_conf[addr] = val & 0xe0;
- break;
-
- case 0x56: /* MDLE delay */
- dev->pci_conf[addr] = val & 0x07;
- break;
-
- case 0x57: /* SDRAM */
- dev->pci_conf[addr] = val & 0xf8;
- break;
-
- case 0x59: /* Buffer strength and current rating */
- dev->pci_conf[addr] = val;
- break;
-
- case 0x5a:
- dev->pci_conf[addr] = val & 0x03;
- break;
-
- /* Undocumented - DRAM bank registers, the exact layout is currently unknown. */
- case 0x60 ... 0x6b:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x70 ... 0x75:
- dev->pci_conf[addr] = val & 0xee;
- sis_5571_shadow_recalc(dev);
- break;
- case 0x76:
- dev->pci_conf[addr] = val & 0xe8;
- sis_5571_shadow_recalc(dev);
- break;
-
- case 0x77: /* Characteristics of non-cacheable area */
- dev->pci_conf[addr] = val & 0x0f;
- break;
-
- case 0x78: /* Allocation of Non-Cacheable area #1 */
- case 0x79: /* NCA1REG2 */
- case 0x7a: /* Allocation of Non-Cacheable area #2 */
- case 0x7b: /* NCA2REG2 */
- dev->pci_conf[addr] = val;
- break;
-
- case 0x80: /* PCI master characteristics */
- dev->pci_conf[addr] = val & 0xfe;
- break;
-
- case 0x81:
- dev->pci_conf[addr] = val & 0xcc;
- break;
-
- case 0x82:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x83: /* CPU to PCI characteristics */
- dev->pci_conf[addr] = val;
- /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */
- break;
-
- case 0x84 ... 0x86:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x87: /* Miscellanea */
- dev->pci_conf[addr] = val & 0xf8;
- break;
-
- case 0x90: /* PMU control register */
- case 0x91: /* Address trap for green function */
- case 0x92:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x93: /* STPCLK# and APM SMI control */
- dev->pci_conf[addr] = val;
-
- if ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02)) {
- smi_raise();
- dev->pci_conf[0x9d] |= 0x01;
- }
- break;
-
- case 0x94: /* 6x86 and Green function control */
- dev->pci_conf[addr] = val & 0xf8;
- break;
-
- case 0x95: /* Test mode control */
- case 0x96: /* Time slot and Programmable 10-bit I/O port definition */
- dev->pci_conf[addr] = val & 0xfb;
- break;
-
- case 0x97: /* programmable 10-bit I/O port address */
- case 0x98: /* Programmable 16-bit I/O port */
- case 0x99 ... 0x9c:
- dev->pci_conf[addr] = val;
- break;
-
- case 0x9d:
- dev->pci_conf[addr] &= val;
- break;
-
- case 0x9e: /* STPCLK# Assertion Timer */
- case 0x9f: /* STPCLK# De-assertion Timer */
- case 0xa0 ... 0xa2:
- dev->pci_conf[addr] = val;
- break;
-
- case 0xa3: /* SMRAM access control and Power supply control */
- dev->pci_conf[addr] = val & 0xd0;
- sis_5571_smram_recalc(dev);
- break;
-
- default:
- break;
- }
- }
-}
-
-static uint8_t
-sis_5571_mem_to_pci_read(int func, int addr, void *priv)
-{
- const sis_5571_t *dev = (sis_5571_t *) priv;
- uint8_t ret = 0xff;
-
- if (func == 0x00) {
- ret = dev->pci_conf[addr];
-
- sis_5571_log("SiS 5571 M2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
- }
-
- return ret;
-}
-
-static void
-sis_5571_pci_to_isa_reset(sis_5571_t *dev)
-{
- /* PCI to ISA Bridge */
- dev->pci_conf_sb[0][0x00] = 0x39;
- dev->pci_conf_sb[0][0x01] = 0x10;
- dev->pci_conf_sb[0][0x02] = 0x08;
- dev->pci_conf_sb[0][0x03] = 0x00;
- dev->pci_conf_sb[0][0x04] = 0x07;
- dev->pci_conf_sb[0][0x05] = 0x00;
- dev->pci_conf_sb[0][0x06] = 0x00;
- dev->pci_conf_sb[0][0x07] = 0x02;
- dev->pci_conf_sb[0][0x08] = 0x01;
- dev->pci_conf_sb[0][0x09] = 0x00;
- dev->pci_conf_sb[0][0x0a] = 0x01;
- dev->pci_conf_sb[0][0x0b] = 0x06;
- dev->pci_conf_sb[0][0x0e] = 0x80;
-
- dev->pci_conf_sb[0][0x40] = 0x00;
- dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80;
- dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80;
- dev->pci_conf_sb[0][0x45] = 0x00;
- dev->pci_conf_sb[0][0x46] = 0x00;
- dev->pci_conf_sb[0][0x47] = 0x00;
- dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x00;
- dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00;
- dev->pci_conf_sb[0][0x61] = 0x80;
- dev->pci_conf_sb[0][0x62] = 0x00;
- dev->pci_conf_sb[0][0x63] = 0x80;
- dev->pci_conf_sb[0][0x64] = 0x00;
- dev->pci_conf_sb[0][0x65] = 0x00;
- dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00;
- dev->pci_conf_sb[0][0x68] = 0x80;
- dev->pci_conf_sb[0][0x69] = dev->pci_conf_sb[0][0x6a] = 0x00;
- dev->pci_conf_sb[0][0x6b] = 0x00;
- dev->pci_conf_sb[0][0x6c] = 0x02;
- dev->pci_conf_sb[0][0x6d] = 0x00;
- dev->pci_conf_sb[0][0x6e] = dev->pci_conf_sb[0][0x6f] = 0x00;
- dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00;
- dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00;
- dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x75] = 0x00;
- dev->pci_conf_sb[0][0x76] = dev->pci_conf_sb[0][0x77] = 0x00;
-
- pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
- pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
- pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
- pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
-
- pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
- pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
- pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
-
- cpu_set_isa_speed(7159091);
- nvr_bank_set(0, 0, dev->nvr);
-}
-
-static void
-sis_5571_pci_to_isa_write(int addr, uint8_t val, void *priv)
-{
- sis_5571_t *dev = (sis_5571_t *) priv;
- uint8_t old;
-
- sis_5571_log("SiS 5571 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val);
-
- switch (addr) {
- default:
- break;
-
- case 0x04: /* Command */
- // dev->pci_conf_sb[0][addr] = val & 0x0f;
- break;
-
- case 0x07: /* Status */
- dev->pci_conf_sb[0][addr] &= ~(val & 0x30);
- break;
-
- case 0x40: /* BIOS Control Register */
- dev->pci_conf_sb[0][addr] = val & 0x3f;
- break;
-
- case 0x41: /* INTA# Remapping Control Register */
- case 0x42: /* INTB# Remapping Control Register */
- case 0x43: /* INTC# Remapping Control Register */
- case 0x44: /* INTD# Remapping Control Register */
- dev->pci_conf_sb[0][addr] = val & 0x8f;
- pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f));
- break;
-
- case 0x45:
- dev->pci_conf_sb[0][addr] = val & 0xec;
- switch (val >> 6) {
- case 0:
- cpu_set_isa_speed(7159091);
- break;
- case 1:
- cpu_set_isa_pci_div(4);
- break;
- case 2:
- cpu_set_isa_pci_div(3);
- break;
-
- default:
- break;
- }
- nvr_bank_set(0, !!(val & 0x08), dev->nvr);
- break;
-
- case 0x46:
- dev->pci_conf_sb[0][addr] = val & 0xec;
- break;
-
- case 0x47: /* DMA Clock and Wait State Control Register */
- dev->pci_conf_sb[0][addr] = val & 0x3e;
- break;
-
- case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
- case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
- case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
- case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x60:
- outb(0x0070, val);
- break;
-
- /* Simply skip MIRQ0, so we can reuse the SiS 551x IDEIRQ infrastructure. */
- case 0x61: /* MIRQ Remapping Control Register */
- sis_5571_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val);
- dev->pci_conf_sb[0][addr] = val & 0xcf;
- if (val & 0x80)
- pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED);
- else
- pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
- break;
-
- case 0x62: /* On-board Device DMA Control Register */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x63: /* IDEIRQ Remapping Control Register */
- sis_5571_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
- dev->pci_conf_sb[0][addr] = val & 0x8f;
- if (val & 0x80)
- pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
- else
- pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
- break;
-
- case 0x64: /* GPIO Control Register */
- dev->pci_conf_sb[0][addr] = val & 0xef;
- break;
-
- case 0x65:
- dev->pci_conf_sb[0][addr] = val & 0x1b;
- break;
-
- case 0x66: /* GPIO Output Mode Control Register */
- case 0x67: /* GPIO Output Mode Control Register */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x68: /* USBIRQ Remapping Control Register */
- sis_5571_log("Set MIRQ routing: USBIRQ -> %02X\n", val);
- dev->pci_conf_sb[0][addr] = val & 0xcf;
- if (val & 0x80)
- pci_set_mirq_routing(PCI_MIRQ3, PCI_IRQ_DISABLED);
- else
- pci_set_mirq_routing(PCI_MIRQ3, val & 0xf);
- break;
-
- case 0x69:
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x6a:
- dev->pci_conf_sb[0][addr] = val & 0xfc;
- break;
-
- case 0x6b:
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x6c:
- dev->pci_conf_sb[0][addr] = val & 0x02;
- break;
-
- case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */
- old = dev->pci_conf_sb[0][addr];
- picint((val ^ old) & val);
- picintc((val ^ old) & ~val);
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */
- old = dev->pci_conf_sb[0][addr];
- picint(((val ^ old) & val) << 8);
- picintc(((val ^ old) & ~val) << 8);
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x70:
- dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x02) | (val & 0xdc);
- break;
-
- case 0x71: /* Type-F DMA Control Register */
- dev->pci_conf_sb[0][addr] = val & 0xef;
- break;
-
- case 0x72: /* SMI Triggered By IRQ/GPIO Control */
- case 0x73: /* SMI Triggered By IRQ/GPIO Control */
- dev->pci_conf_sb[0][addr] = val;
- break;
-
- case 0x74: /* System Standby Timer Reload,
- System Standby State Exit And Throttling State Exit Control */
- case 0x75: /* System Standby Timer Reload,
- System Standby State Exit And Throttling State Exit Control */
- case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
- case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
- dev->pci_conf_sb[0][addr] = val;
- break;
- }
-}
-
-static uint8_t
-sis_5571_pci_to_isa_read(int addr, void *priv)
-{
- const sis_5571_t *dev = (sis_5571_t *) priv;
- uint8_t ret = 0xff;
-
- switch (addr) {
- default:
- ret = dev->pci_conf_sb[0][addr];
- break;
- case 0x4c ... 0x4f:
- ret = pic_read_icw(0, addr & 0x03);
- break;
- case 0x50 ... 0x53:
- ret = pic_read_icw(1, addr & 0x03);
- break;
- case 0x54 ... 0x55:
- ret = pic_read_ocw(0, addr & 0x01);
- break;
- case 0x56 ... 0x57:
- ret = pic_read_ocw(1, addr & 0x01);
- break;
- case 0x58 ... 0x5f:
- ret = dev->pit_read_reg(dev->pit, addr & 0x07);
- break;
- case 0x60:
- ret = inb(0x0070);
- break;
- }
-
- sis_5571_log("SiS 5571 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret);
-
- return ret;
-}
-
-static void
-sis_5571_ide_irq_handler(sis_5571_t *dev)
-{
- if (dev->pci_conf_sb[1][0x09] & 0x01) {
- /* Primary IDE is native. */
- sis_5571_log("Primary IDE IRQ mode: Native, Native\n");
- sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X);
- } else {
- /* Primary IDE is legacy. */
- sis_5571_log("Primary IDE IRQ mode: IRQ14, IRQ15\n");
- sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY);
- }
-
- if (dev->pci_conf_sb[1][0x09] & 0x04) {
- /* Secondary IDE is native. */
- sis_5571_log("Secondary IDE IRQ mode: Native, Native\n");
- sff_set_irq_mode(dev->bm[1], IRQ_MODE_SIS_551X);
- } else {
- /* Secondary IDE is legacy. */
- sis_5571_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n");
- sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
- }
-}
-
-static void
-sis_5571_ide_handler(sis_5571_t *dev)
-{
- uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01;
-
- uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe;
- uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe;
- uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe;
- uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe;
-
- uint16_t current_pri_base;
- uint16_t current_pri_side;
- uint16_t current_sec_base;
- uint16_t current_sec_side;
-
- /* Primary Channel Programming */
- current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr;
- current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr;
-
- /* Secondary Channel Programming */
- current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr;
- current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr;
-
- sis_5571_log("sis_5571_ide_handler(): Disabling primary IDE...\n");
- ide_pri_disable();
- sis_5571_log("sis_5571_ide_handler(): Disabling secondary IDE...\n");
- ide_sec_disable();
-
- if (ide_io_on) {
- /* Primary Channel Setup */
- if (dev->pci_conf_sb[1][0x4a] & 0x02) {
- sis_5571_log("sis_5571_ide_handler(): Primary IDE base now %04X...\n", current_pri_base);
- ide_set_base(0, current_pri_base);
- sis_5571_log("sis_5571_ide_handler(): Primary IDE side now %04X...\n", current_pri_side);
- ide_set_side(0, current_pri_side);
-
- sis_5571_log("sis_5571_ide_handler(): Enabling primary IDE...\n");
- ide_pri_enable();
-
- sis_5571_log("SiS 5571 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side);
- }
-
- /* Secondary Channel Setup */
- if (dev->pci_conf_sb[1][0x4a] & 0x04) {
- sis_5571_log("sis_5571_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base);
- ide_set_base(1, current_sec_base);
- sis_5571_log("sis_5571_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side);
- ide_set_side(1, current_sec_side);
-
- sis_5571_log("sis_5571_ide_handler(): Enabling secondary IDE...\n");
- ide_sec_enable();
-
- sis_5571_log("SiS 5571: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side);
- }
- }
-
- sff_bus_master_handler(dev->bm[0], ide_io_on,
- ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0);
- sff_bus_master_handler(dev->bm[1], ide_io_on,
- ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8);
-}
-
-static void
-sis_5571_ide_reset(sis_5571_t *dev)
-{
- /* PCI IDE */
- dev->pci_conf_sb[1][0x00] = 0x39;
- dev->pci_conf_sb[1][0x01] = 0x10;
- dev->pci_conf_sb[1][0x02] = 0x13;
- dev->pci_conf_sb[1][0x03] = 0x55;
- dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00;
- dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00;
- dev->pci_conf_sb[1][0x08] = 0xc0;
- dev->pci_conf_sb[1][0x09] = 0x8a;
- dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01;
- dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00;
- dev->pci_conf_sb[1][0x0e] = 0x80;
- dev->pci_conf_sb[1][0x0f] = 0x00;
- dev->pci_conf_sb[1][0x10] = 0xf1;
- dev->pci_conf_sb[1][0x11] = 0x01;
- dev->pci_conf_sb[1][0x14] = 0xf5;
- dev->pci_conf_sb[1][0x15] = 0x03;
- dev->pci_conf_sb[1][0x18] = 0x71;
- dev->pci_conf_sb[1][0x19] = 0x01;
- dev->pci_conf_sb[1][0x1c] = 0x75;
- dev->pci_conf_sb[1][0x1d] = 0x03;
- dev->pci_conf_sb[1][0x20] = 0x01;
- dev->pci_conf_sb[1][0x21] = 0xf0;
- dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00;
- dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00;
- dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00;
- dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00;
- dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00;
-#ifdef DATASHEET
- dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00;
-#else
- /* The only Linux lspci listing I could find of this chipset,
- shows a subsystem of 0058:0000. */
- dev->pci_conf_sb[1][0x2c] = 0x58;
- dev->pci_conf_sb[1][0x2d] = 0x00;
-#endif
- dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00;
- dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00;
- dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00;
- dev->pci_conf_sb[1][0x40] = dev->pci_conf_sb[1][0x41] = 0x00;
- dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00;
- dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00;
- dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00;
- dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00;
- dev->pci_conf_sb[1][0x4a] = 0x06;
- dev->pci_conf_sb[1][0x4b] = 0x00;
- dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00;
- dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00;
-
- sis_5571_ide_irq_handler(dev);
- sis_5571_ide_handler(dev);
-
- sff_bus_master_reset(dev->bm[0]);
- sff_bus_master_reset(dev->bm[1]);
-}
-
-static void
-sis_5571_ide_write(int addr, uint8_t val, void *priv)
-{
- sis_5571_t *dev = (sis_5571_t *) priv;
-
- sis_5571_log("SiS 5571 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val);
-
- switch (addr) {
- default:
- break;
-
- case 0x04: /* Command low byte */
- dev->pci_conf_sb[1][addr] = val & 0x05;
- sis_5571_ide_handler(dev);
- break;
- case 0x06: /* Status low byte */
- dev->pci_conf_sb[1][addr] = val & 0x20;
- break;
- case 0x07: /* Status high byte */
- dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38);
- break;
- case 0x09: /* Programming Interface Byte */
- dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x45);
- sis_5571_ide_irq_handler(dev);
- sis_5571_ide_handler(dev);
- break;
- case 0x0d: /* Latency Timer */
- dev->pci_conf_sb[1][addr] = val;
- break;
-
- /* Primary Base Address */
- case 0x10:
- case 0x11:
- case 0x14:
- case 0x15:
- fallthrough;
-
- /* Secondary Base Address */
- case 0x18:
- case 0x19:
- case 0x1c:
- case 0x1d:
- fallthrough;
-
- /* Bus Mastering Base Address */
- case 0x20:
- case 0x21:
- if (addr == 0x20)
- dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01;
- else
- dev->pci_conf_sb[1][addr] = val;
- sis_5571_ide_handler(dev);
- break;
-
- /* The only Linux lspci listing I could find of this chipset,
- does not show any BIOS bar, therefore writes to that are disabled. */
-#ifdef DATASHEET
- case 0x30: /* Expansion ROM Base Address */
- case 0x31: /* Expansion ROM Base Address */
- case 0x32: /* Expansion ROM Base Address */
- case 0x33: /* Expansion ROM Base Address */
- dev->pci_conf_sb[1][addr] = val;
- break;
-#endif
-
- case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
- case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
- case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
- case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
- case 0x48: /* IDE Command Recovery Time Control */
- dev->pci_conf_sb[1][addr] = val & 0x0f;
- break;
-
- case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
- case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
- case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
- case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
- case 0x49: /* IDE Command Active Time Control */
- dev->pci_conf_sb[1][addr] = val & 0x07;
- break;
-
- case 0x4a: /* IDE General Control Register 0 */
- dev->pci_conf_sb[1][addr] = val & 0xaf;
- sis_5571_ide_handler(dev);
- break;
-
- case 0x4b: /* IDE General Control register 1 */
- dev->pci_conf_sb[1][addr] = val;
- break;
-
- case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
- case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
- case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
- case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
- dev->pci_conf_sb[1][addr] = val;
- break;
- }
-}
-
-static uint8_t
-sis_5571_ide_read(int addr, void *priv)
+sis_5571_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5571_t *dev = (sis_5571_t *) priv;
- uint8_t ret = 0xff;
-
- switch (addr) {
- default:
- ret = dev->pci_conf_sb[1][addr];
- break;
-
- case 0x09:
- ret = dev->pci_conf_sb[1][addr];
- if (dev->pci_conf_sb[1][0x09] & 0x40)
- ret |= ((dev->pci_conf_sb[1][0x4a] & 0x06) << 3);
- break;
-
- case 0x3d:
- ret = (dev->pci_conf_sb[1][0x09] & 0x05) ? PCI_INTA : 0x00;
- break;
- }
-
- sis_5571_log("SiS 5571 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret);
-
- return ret;
-}
-
-/* SiS 5571 unknown I/O port (second USB PCI BAR). */
-static void
-sis_5571_usb_unk_write(uint16_t addr, uint8_t val, void *priv)
-{
- sis_5571_t *dev = (sis_5571_t *) priv;
-
- addr = (addr - dev->usb_unk_base) & 0x07;
- sis_5571_log("SiS 5571 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val);
+ sis_5571_log("SiS 5571: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
- dev->usb_unk_regs[addr] = val;
+ if (func == 0x00)
+ sis_5571_host_to_pci_write(addr, val, dev->h2p);
}
static uint8_t
-sis_5571_usb_unk_read(uint16_t addr, void *priv)
+sis_5571_read(int func, int addr, void *priv)
{
const sis_5571_t *dev = (sis_5571_t *) priv;
uint8_t ret = 0xff;
- addr = (addr - dev->usb_unk_base) & 0x07;
+ if (func == 0x00)
+ ret = sis_5571_host_to_pci_read(addr, dev->h2p);
- ret = dev->usb_unk_regs[addr & 0x07];
-
- sis_5571_log("SiS 5571 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret);
+ sis_5571_log("SiS 5571: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
-sis_5571_usb_reset(sis_5571_t *dev)
-{
- /* USB */
- dev->pci_conf_sb[2][0x00] = 0x39;
- dev->pci_conf_sb[2][0x01] = 0x10;
- dev->pci_conf_sb[2][0x02] = 0x01;
- dev->pci_conf_sb[2][0x03] = 0x70;
- dev->pci_conf_sb[2][0x04] = dev->pci_conf_sb[1][0x05] = 0x00;
- dev->pci_conf_sb[2][0x06] = 0x00;
- dev->pci_conf_sb[2][0x07] = 0x02;
- dev->pci_conf_sb[2][0x08] = 0xb0;
- dev->pci_conf_sb[2][0x09] = 0x10;
- dev->pci_conf_sb[2][0x0a] = 0x03;
- dev->pci_conf_sb[2][0x0b] = 0x0c;
- dev->pci_conf_sb[2][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00;
- dev->pci_conf_sb[2][0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */;
- dev->pci_conf_sb[2][0x0f] = 0x00;
- dev->pci_conf_sb[2][0x10] = 0x00;
- dev->pci_conf_sb[2][0x11] = 0x00;
- dev->pci_conf_sb[2][0x12] = 0x00;
- dev->pci_conf_sb[2][0x13] = 0x00;
- dev->pci_conf_sb[2][0x14] = 0x01;
- dev->pci_conf_sb[2][0x15] = 0x00;
- dev->pci_conf_sb[2][0x16] = 0x00;
- dev->pci_conf_sb[2][0x17] = 0x00;
- dev->pci_conf_sb[2][0x3c] = 0x00;
- dev->pci_conf_sb[2][0x3d] = PCI_INTA;
- dev->pci_conf_sb[2][0x3e] = 0x00;
- dev->pci_conf_sb[2][0x3f] = 0x00;
-
- ohci_update_mem_mapping(dev->usb,
- dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12],
- dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][0x04] & 0x02);
-
- if (dev->usb_unk_base != 0x0000) {
- io_removehandler(dev->usb_unk_base, 0x0002,
- sis_5571_usb_unk_read, NULL, NULL,
- sis_5571_usb_unk_write, NULL, NULL, dev);
- }
-
- dev->usb_unk_base = 0x0000;
-
- memset(dev->usb_unk_regs, 0x00, sizeof(dev->usb_unk_regs));
-}
-
-static void
-sis_5571_usb_write(int addr, uint8_t val, void *priv)
-{
- sis_5571_t *dev = (sis_5571_t *) priv;
-
- sis_5571_log("SiS 5571 USB: [W] dev->pci_conf_sb[2][%02X] = %02X\n", addr, val);
-
- if (dev->pci_conf_sb[0][0x68] & 0x40) switch (addr) {
- default:
- break;
-
- case 0x04: /* Command - Low Byte */
- dev->pci_conf_sb[2][addr] = val & 0x47;
- if (dev->usb_unk_base != 0x0000) {
- io_removehandler(dev->usb_unk_base, 0x0002,
- sis_5571_usb_unk_read, NULL, NULL,
- sis_5571_usb_unk_write, NULL, NULL, dev);
- if (dev->pci_conf_sb[2][0x04] & 0x01)
- io_sethandler(dev->usb_unk_base, 0x0002,
- sis_5571_usb_unk_read, NULL, NULL,
- sis_5571_usb_unk_write, NULL, NULL, dev);
- }
- ohci_update_mem_mapping(dev->usb,
- dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12],
- dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][0x04] & 0x02);
- break;
-
- case 0x05: /* Command - High Byte */
- dev->pci_conf_sb[2][addr] = val & 0x01;
- break;
-
- case 0x07: /* Status - High Byte */
- dev->pci_conf_sb[2][addr] &= ~(val & 0xf9);
- break;
-
- case 0x0d: /* Latency Timer */
- dev->pci_conf_sb[2][addr] = val;
- break;
-
- case 0x11: /* Memory Space Base Address Register */
- case 0x12: /* Memory Space Base Address Register */
- case 0x13: /* Memory Space Base Address Register */
- dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0xf0 : 0xff);
- ohci_update_mem_mapping(dev->usb,
- dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12],
- dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 0x02);
- break;
-
- case 0x14: /* IO Space Base Address Register */
- case 0x15: /* IO Space Base Address Register */
- if (dev->usb_unk_base != 0x0000) {
- io_removehandler(dev->usb_unk_base, 0x0002,
- sis_5571_usb_unk_read, NULL, NULL,
- sis_5571_usb_unk_write, NULL, NULL, dev);
- }
- dev->pci_conf_sb[2][addr] = val;
- dev->usb_unk_base = (dev->pci_conf_sb[2][0x14] & 0xf8) |
- (dev->pci_conf_sb[2][0x15] << 8);
- if (dev->usb_unk_base != 0x0000) {
- io_sethandler(dev->usb_unk_base, 0x0002,
- sis_5571_usb_unk_read, NULL, NULL,
- sis_5571_usb_unk_write, NULL, NULL, dev);
- }
- break;
-
- case 0x3c: /* Interrupt Line */
- dev->pci_conf_sb[2][addr] = val;
- break;
- }
-}
-
-static uint8_t
-sis_5571_usb_read(int addr, void *priv)
+sis_5572_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5571_t *dev = (sis_5571_t *) priv;
- uint8_t ret = 0xff;
-
- if (dev->pci_conf_sb[0][0x68] & 0x40) {
- ret = dev->pci_conf_sb[2][addr];
- sis_5571_log("SiS 5571 USB: [R] dev->pci_conf_sb[2][%02X] = %02X\n", addr, ret);
- }
+ sis_5571_log("SiS 5572: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
- return ret;
-}
-
-static void
-sis_5571_sb_write(int func, int addr, uint8_t val, void *priv)
-{
switch (func) {
case 0x00:
- sis_5571_pci_to_isa_write(addr, val, priv);
+ sis_5513_pci_to_isa_write(addr, val, dev->p2i);
break;
case 0x01:
- sis_5571_ide_write(addr, val, priv);
+ sis_5513_ide_write(addr, val, dev->ide);
break;
case 0x02:
- sis_5571_usb_write(addr, val, priv);
+ sis_5572_usb_write(addr, val, dev->usb);
break;
}
}
static uint8_t
-sis_5571_sb_read(int func, int addr, void *priv)
+sis_5572_read(int func, int addr, void *priv)
{
+ const sis_5571_t *dev = (sis_5571_t *) priv;
uint8_t ret = 0xff;
switch (func) {
case 0x00:
- ret = sis_5571_pci_to_isa_read(addr, priv);
+ ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
break;
case 0x01:
- ret = sis_5571_ide_read(addr, priv);
+ ret = sis_5513_ide_read(addr, dev->ide);
break;
case 0x02:
- ret = sis_5571_usb_read(addr, priv);
+ ret = sis_5572_usb_read(addr, dev->usb);
break;
}
- return ret;
-}
-
-static void
-sis_5571_reset(void *priv)
-{
- sis_5571_t *dev = (sis_5571_t *) priv;
-
- /* Memory/PCI Bridge */
- sis_5571_mem_to_pci_reset(dev);
-
- /* PCI to ISA bridge */
- sis_5571_pci_to_isa_reset(dev);
+ sis_5571_log("SiS 5572: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
- /* IDE Controller */
- sis_5571_ide_reset(dev);
-
- /* USB Controller */
- sis_5571_usb_reset(dev);
+ return ret;
}
static void
@@ -1184,7 +146,6 @@ sis_5571_close(void *priv)
{
sis_5571_t *dev = (sis_5571_t *) priv;
- smram_del(dev->smram);
free(dev);
}
@@ -1192,44 +153,18 @@ static void *
sis_5571_init(UNUSED(const device_t *info))
{
sis_5571_t *dev = (sis_5571_t *) calloc(1, sizeof(sis_5571_t));
- uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
-
- /* Device 0: Memory/PCI Bridge */
- pci_add_card(PCI_ADD_NORTHBRIDGE,
- sis_5571_mem_to_pci_read, sis_5571_mem_to_pci_write, dev, &dev->nb_slot);
- /* Device 1: Southbridge */
- pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5571_sb_read, sis_5571_sb_write, dev, &dev->sb_slot);
-
- /* MIRQ */
- pci_enable_mirq(1);
-
- /* IDEIRQ */
- pci_enable_mirq(2);
-
- /* USBIRQ */
- pci_enable_mirq(3);
-
- /* Port 92h */
- dev->port_92 = device_add(&port_92_device);
-
- /* SFF IDE */
- dev->bm[0] = device_add_inst(&sff8038i_device, 1);
- dev->bm[1] = device_add_inst(&sff8038i_device, 2);
-
- /* SMRAM */
- dev->smram = smram_add();
-
- /* PIT */
- dev->pit = device_find_first_priv(DEVICE_PIT);
- dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg;
- /* NVR */
- dev->nvr = device_add(&at_mb_nvr_device);
+ /* Device 0: SiS 5571 */
+ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5571_read, sis_5571_write, dev, &dev->nb_slot);
+ /* Device 1: SiS 5572 */
+ pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5572_read, sis_5572_write, dev, &dev->sb_slot);
- /* USB */
- dev->usb = device_add(&usb_device);
+ dev->sis = device_add(&sis_55xx_common_device);
- sis_5571_reset(dev);
+ dev->h2p = device_add_linked(&sis_5571_h2p_device, dev->sis);
+ dev->p2i = device_add_linked(&sis_5572_p2i_device, dev->sis);
+ dev->ide = device_add_linked(&sis_5572_ide_device, dev->sis);
+ dev->usb = device_add_linked(&sis_5572_usb_device, dev->sis);
return dev;
}
@@ -1241,7 +176,7 @@ const device_t sis_5571_device = {
.local = 0,
.init = sis_5571_init,
.close = sis_5571_close,
- .reset = sis_5571_reset,
+ .reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
diff --git a/src/chipset/sis_5571_h2p.c b/src/chipset/sis_5571_h2p.c
new file mode 100644
index 0000000000..4a4ee9b83d
--- /dev/null
+++ b/src/chipset/sis_5571_h2p.c
@@ -0,0 +1,458 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5571 Host to PCI bridge.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/spd.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+#include <86box/agpgart.h>
+
+#ifdef ENABLE_SIS_5571_HOST_TO_PCI_LOG
+int sis_5571_host_to_pci_do_log = ENABLE_SIS_5571_HOST_TO_PCI_LOG;
+
+static void
+sis_5571_host_to_pci_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5571_host_to_pci_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5571_host_to_pci_log(fmt, ...)
+#endif
+
+typedef struct sis_5571_host_to_pci_t {
+ uint8_t pci_conf[256];
+ uint8_t states[7];
+
+ sis_55xx_common_t *sis;
+
+ smram_t *smram;
+} sis_5571_host_to_pci_t;
+
+static void
+sis_5571_shadow_recalc(sis_5571_host_to_pci_t *dev)
+{
+ int state;
+ uint32_t base;
+
+ for (uint8_t i = 0x70; i <= 0x76; i++) {
+ if (i == 0x76) {
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
+ state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(0xf0000, 0x10000, state);
+ sis_5571_host_to_pci_log("000F0000-000FFFFF\n");
+ }
+ } else {
+ base = ((i & 0x07) << 15) + 0xc0000;
+
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
+ state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(base, 0x4000, state);
+ sis_5571_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+ }
+
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
+ state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(base + 0x4000, 0x4000, state);
+ sis_5571_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
+ }
+ }
+
+ dev->states[i & 0x0f] = dev->pci_conf[i];
+ }
+
+ flushmmucache_nopc();
+}
+
+static void
+sis_5571_smram_recalc(sis_5571_host_to_pci_t *dev)
+{
+ smram_disable_all();
+
+ switch (dev->pci_conf[0xa3] >> 6) {
+ case 0:
+ smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+ case 1:
+ smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+ case 2:
+ smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+ case 3:
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+
+ default:
+ break;
+ }
+
+ flushmmucache();
+}
+
+void
+sis_5571_host_to_pci_write(int addr, uint8_t val, void *priv)
+{
+ sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
+
+ sis_5571_host_to_pci_log("SiS 5571 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ default:
+ break;
+
+ case 0x04: /* Command - low byte */
+ case 0x05: /* Command - high byte */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] &= ~(val & 0xb8);
+ break;
+
+ case 0x0d: /* Master latency timer */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x50: /* Host Interface and DRAM arbiter */
+ dev->pci_conf[addr] = val & 0xec;
+ break;
+
+ case 0x51: /* CACHE */
+ dev->pci_conf[addr] = val;
+ cpu_cache_ext_enabled = !!(val & 0x40);
+ cpu_update_waitstates();
+ break;
+
+ case 0x52:
+ dev->pci_conf[addr] = val & 0xd0;
+ break;
+
+ case 0x53: /* DRAM */
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x54: /* FP/EDO */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x55:
+ dev->pci_conf[addr] = val & 0xe0;
+ break;
+
+ case 0x56: /* MDLE delay */
+ dev->pci_conf[addr] = val & 0x07;
+ break;
+
+ case 0x57: /* SDRAM */
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x59: /* Buffer strength and current rating */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x5a:
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+
+ /* Undocumented - DRAM bank registers, the exact layout is currently unknown. */
+ case 0x60 ... 0x6b:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x70 ... 0x75:
+ dev->pci_conf[addr] = val & 0xee;
+ sis_5571_shadow_recalc(dev);
+ break;
+ case 0x76:
+ dev->pci_conf[addr] = val & 0xe8;
+ sis_5571_shadow_recalc(dev);
+ break;
+
+ case 0x77: /* Characteristics of non-cacheable area */
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ case 0x78: /* Allocation of Non-Cacheable area #1 */
+ case 0x79: /* NCA1REG2 */
+ case 0x7a: /* Allocation of Non-Cacheable area #2 */
+ case 0x7b: /* NCA2REG2 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x80: /* PCI master characteristics */
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x81:
+ dev->pci_conf[addr] = val & 0xcc;
+ break;
+
+ case 0x82:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x83: /* CPU to PCI characteristics */
+ dev->pci_conf[addr] = val;
+ /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */
+ break;
+
+ case 0x84 ... 0x86:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x87: /* Miscellanea */
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x90: /* PMU control register */
+ case 0x91: /* Address trap for green function */
+ case 0x92:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x93: /* STPCLK# and APM SMI control */
+ dev->pci_conf[addr] = val;
+
+ if ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02)) {
+ smi_raise();
+ dev->pci_conf[0x9d] |= 0x01;
+ }
+ break;
+
+ case 0x94: /* 6x86 and Green function control */
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x95: /* Test mode control */
+ case 0x96: /* Time slot and Programmable 10-bit I/O port definition */
+ dev->pci_conf[addr] = val & 0xfb;
+ break;
+
+ case 0x97: /* programmable 10-bit I/O port address */
+ case 0x98: /* Programmable 16-bit I/O port */
+ case 0x99 ... 0x9c:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x9d:
+ dev->pci_conf[addr] &= val;
+ break;
+
+ case 0x9e: /* STPCLK# Assertion Timer */
+ case 0x9f: /* STPCLK# De-assertion Timer */
+ case 0xa0 ... 0xa2:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0xa3: /* SMRAM access control and Power supply control */
+ dev->pci_conf[addr] = val & 0xd0;
+ sis_5571_smram_recalc(dev);
+ break;
+ }
+}
+
+uint8_t
+sis_5571_host_to_pci_read(int addr, void *priv)
+{
+ const sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
+ uint8_t ret = 0xff;
+
+ ret = dev->pci_conf[addr];
+
+ sis_5571_host_to_pci_log("SiS 5571 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5571_host_to_pci_reset(void *priv)
+{
+ sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x71;
+ dev->pci_conf[0x03] = 0x55;
+ dev->pci_conf[0x04] = 0x05;
+ dev->pci_conf[0x05] = 0x00;
+ dev->pci_conf[0x06] = 0x00;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x00;
+ dev->pci_conf[0x09] = 0x00;
+ dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x0c] = 0x00;
+ dev->pci_conf[0x0d] = 0x00;
+ dev->pci_conf[0x0e] = 0x00;
+ dev->pci_conf[0x0f] = 0x00;
+
+ dev->pci_conf[0x50] = 0x00;
+ dev->pci_conf[0x51] = 0x00;
+ dev->pci_conf[0x52] = 0x00;
+ dev->pci_conf[0x53] = 0x00;
+ dev->pci_conf[0x54] = 0x54;
+ dev->pci_conf[0x55] = 0x54;
+ dev->pci_conf[0x56] = 0x03;
+ dev->pci_conf[0x57] = 0x00;
+ dev->pci_conf[0x58] = 0x00;
+ dev->pci_conf[0x59] = 0x00;
+ dev->pci_conf[0x5a] = 0x00;
+
+ /* Undocumented DRAM bank registers. */
+ dev->pci_conf[0x60] = dev->pci_conf[0x62] = 0x04;
+ dev->pci_conf[0x64] = dev->pci_conf[0x66] = 0x04;
+ dev->pci_conf[0x68] = dev->pci_conf[0x6a] = 0x04;
+ dev->pci_conf[0x61] = dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x63] = dev->pci_conf[0x67] = 0x80;
+ dev->pci_conf[0x69] = 0x00;
+ dev->pci_conf[0x6b] = 0x80;
+
+ dev->pci_conf[0x70] = 0x00;
+ dev->pci_conf[0x71] = 0x00;
+ dev->pci_conf[0x72] = 0x00;
+ dev->pci_conf[0x73] = 0x00;
+ dev->pci_conf[0x74] = 0x00;
+ dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x76] = 0x00;
+
+ dev->pci_conf[0x77] = 0x00;
+ dev->pci_conf[0x78] = 0x00;
+ dev->pci_conf[0x79] = 0x00;
+ dev->pci_conf[0x7a] = 0x00;
+ dev->pci_conf[0x7b] = 0x00;
+
+ dev->pci_conf[0x80] = 0x00;
+ dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x82] = 0x00;
+ dev->pci_conf[0x83] = 0x00;
+ dev->pci_conf[0x84] = 0x00;
+ dev->pci_conf[0x85] = 0x00;
+ dev->pci_conf[0x86] = 0x00;
+ dev->pci_conf[0x87] = 0x00;
+
+ dev->pci_conf[0x8c] = 0x00;
+ dev->pci_conf[0x8d] = 0x00;
+ dev->pci_conf[0x8e] = 0x00;
+ dev->pci_conf[0x8f] = 0x00;
+
+ dev->pci_conf[0x90] = 0x00;
+ dev->pci_conf[0x91] = 0x00;
+ dev->pci_conf[0x92] = 0x00;
+ dev->pci_conf[0x93] = 0x00;
+ dev->pci_conf[0x93] = 0x00;
+ dev->pci_conf[0x94] = 0x00;
+ dev->pci_conf[0x95] = 0x00;
+ dev->pci_conf[0x96] = 0x00;
+ dev->pci_conf[0x97] = 0x00;
+ dev->pci_conf[0x98] = 0x00;
+ dev->pci_conf[0x99] = 0x00;
+ dev->pci_conf[0x9a] = 0x00;
+ dev->pci_conf[0x9b] = 0x00;
+ dev->pci_conf[0x9c] = 0x00;
+ dev->pci_conf[0x9d] = 0x00;
+ dev->pci_conf[0x9e] = 0xff;
+ dev->pci_conf[0x9f] = 0xff;
+
+ dev->pci_conf[0xa0] = 0xff;
+ dev->pci_conf[0xa1] = 0x00;
+ dev->pci_conf[0xa2] = 0xff;
+ dev->pci_conf[0xa3] = 0x00;
+
+ cpu_cache_ext_enabled = 0;
+ cpu_update_waitstates();
+
+ sis_5571_smram_recalc(dev);
+ sis_5571_shadow_recalc(dev);
+
+ flushmmucache();
+}
+
+static void
+sis_5571_host_to_pci_close(void *priv)
+{
+ sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+static void *
+sis_5571_host_to_pci_init(UNUSED(const device_t *info))
+{
+ sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) calloc(1, sizeof(sis_5571_host_to_pci_t));
+
+ dev->sis = device_get_common_priv();
+
+ /* SMRAM */
+ dev->smram = smram_add();
+
+ sis_5571_host_to_pci_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5571_h2p_device = {
+ .name = "SiS 5571 Host to PCI bridge",
+ .internal_name = "sis_5571_host_to_pci",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5571_host_to_pci_init,
+ .close = sis_5571_host_to_pci_close,
+ .reset = sis_5571_host_to_pci_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5571_old.c b/src/chipset/sis_5571_old.c
new file mode 100644
index 0000000000..f130ecd8a0
--- /dev/null
+++ b/src/chipset/sis_5571_old.c
@@ -0,0 +1,772 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5571 Chipset.
+ *
+ *
+ *
+ * Authors: Tiseno100,
+ *
+ * Copyright 2021 Tiseno100.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/smram.h>
+#include <86box/usb.h>
+
+#include <86box/chipset.h>
+
+/* Shadow RAM */
+#define LSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
+#define LSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
+#define MSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
+#define MSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
+#define SYSTEM_READ ((dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
+#define SYSTEM_WRITE ((dev->pci_conf[0x76] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
+
+/* IDE Flags (1 Native / 0 Compatibility)*/
+#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1)
+#define SECONDARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 4)
+#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8)
+#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2)
+#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8)
+#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2)
+#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8))
+
+#ifdef ENABLE_SIS_5571_LOG
+int sis_5571_do_log = ENABLE_SIS_5571_LOG;
+
+static void
+sis_5571_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5571_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5571_log(fmt, ...)
+#endif
+
+typedef struct sis_5571_t {
+ uint8_t nb_slot;
+ uint8_t sb_slot;
+ uint8_t pad;
+ uint8_t usb_irq_state;
+
+ uint8_t pci_conf[256];
+ uint8_t pci_conf_sb[3][256];
+
+ port_92_t *port_92;
+ sff8038i_t *ide_drive[2];
+ smram_t *smram;
+ usb_t *usb;
+} sis_5571_t;
+
+static void
+sis_5571_shadow_recalc(int cur_reg, sis_5571_t *dev)
+{
+ if (cur_reg != 0x76) {
+ mem_set_mem_state_both(0xc0000 + (0x8000 * (cur_reg & 0x07)), 0x4000, LSB_READ | LSB_WRITE);
+ mem_set_mem_state_both(0xc4000 + (0x8000 * (cur_reg & 0x07)), 0x4000, MSB_READ | MSB_WRITE);
+ } else
+ mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE);
+
+ flushmmucache_nopc();
+}
+
+static void
+sis_5571_smm_recalc(sis_5571_t *dev)
+{
+ smram_disable_all();
+
+ switch ((dev->pci_conf[0xa3] & 0xc0) >> 6) {
+ case 0x00:
+ smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1);
+ break;
+ case 0x01:
+ smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1);
+ break;
+ case 0x02:
+ smram_enable(dev->smram, 0xe0000, 0xb0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1);
+ break;
+ case 0x03:
+ smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1);
+ break;
+
+ default:
+ break;
+ }
+
+ flushmmucache();
+}
+
+void
+sis_5571_ide_handler(sis_5571_t *dev)
+{
+ ide_pri_disable();
+ ide_sec_disable();
+ if (dev->pci_conf_sb[1][4] & 1) {
+ if (dev->pci_conf_sb[1][0x4a] & 4) {
+ ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0);
+ ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6);
+ ide_pri_enable();
+ }
+ if (dev->pci_conf_sb[1][0x4a] & 2) {
+ ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170);
+ ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376);
+ ide_sec_enable();
+ }
+ }
+}
+
+void
+sis_5571_bm_handler(sis_5571_t *dev)
+{
+ sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE);
+ sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8);
+}
+
+static void
+memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *priv)
+{
+ sis_5571_t *dev = (sis_5571_t *) priv;
+
+ switch (addr) {
+ case 0x04: /* Command - low byte */
+ case 0x05: /* Command - high byte */
+ dev->pci_conf[addr] |= val;
+ break;
+
+ case 0x06: /* Status - Low Byte */
+ dev->pci_conf[addr] &= val;
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] &= val & 0xbe;
+ break;
+
+ case 0x0d: /* Master latency timer */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x50: /* Host Interface and DRAM arbiter */
+ dev->pci_conf[addr] = val & 0xec;
+ break;
+
+ case 0x51: /* CACHE */
+ dev->pci_conf[addr] = val;
+ cpu_cache_ext_enabled = !!(val & 0x40);
+ cpu_update_waitstates();
+ break;
+
+ case 0x52:
+ dev->pci_conf[addr] = val & 0xd0;
+ break;
+
+ case 0x53: /* DRAM */
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x54: /* FP/EDO */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x55:
+ dev->pci_conf[addr] = val & 0xe0;
+ break;
+
+ case 0x56: /* MDLE delay */
+ case 0x57: /* SDRAM */
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x59: /* Buffer strength and current rating */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x5a:
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+
+ case 0x60: /* Undocumented */
+ case 0x61: /* Undocumented */
+ case 0x62: /* Undocumented */
+ case 0x63: /* Undocumented */
+ case 0x64: /* Undocumented */
+ case 0x65: /* Undocumented */
+ case 0x66: /* Undocumented */
+ case 0x67: /* Undocumented */
+ case 0x68: /* Undocumented */
+ case 0x69: /* Undocumented */
+ case 0x6a: /* Undocumented */
+ case 0x6b: /* Undocumented */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76: /* Attribute of shadow RAM for BIOS area */
+ dev->pci_conf[addr] = val & ((addr != 0x76) ? 0xee : 0xe8);
+ sis_5571_shadow_recalc(addr, dev);
+ sis_5571_smm_recalc(dev);
+ break;
+
+ case 0x77: /* Characteristics of non-cacheable area */
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ case 0x78: /* Allocation of Non-Cacheable area #1 */
+ case 0x79: /* NCA1REG2 */
+ case 0x7a: /* Allocation of Non-Cacheable area #2 */
+ case 0x7b: /* NCA2REG2 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x80: /* PCI master characteristics */
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x81:
+ dev->pci_conf[addr] = val & 0xcc;
+ break;
+
+ case 0x82:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x83: /* CPU to PCI characteristics */
+ dev->pci_conf[addr] = val;
+ port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80));
+ break;
+
+ case 0x84:
+ case 0x85:
+ case 0x86:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x87: /* Miscellanea */
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x90: /* PMU control register */
+ case 0x91: /* Address trap for green function */
+ case 0x92:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x93: /* STPCLK# and APM SMI control */
+ dev->pci_conf[addr] = val;
+
+ if ((dev->pci_conf[0x9b] & 1) && !!(val & 2)) {
+ smi_raise();
+ dev->pci_conf[0x9d] |= 1;
+ }
+ break;
+
+ case 0x94: /* 6x86 and Green function control */
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x95: /* Test mode control */
+ case 0x96: /* Time slot and Programmable 10-bit I/O port definition */
+ dev->pci_conf[addr] = val & 0xfb;
+ break;
+
+ case 0x97: /* programmable 10-bit I/O port address */
+ case 0x98: /* Programmable 16-bit I/O port */
+ case 0x99:
+ case 0x9a:
+ case 0x9b:
+ case 0x9c:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x9d:
+ dev->pci_conf[addr] &= val;
+ break;
+
+ case 0x9e: /* STPCLK# Assertion Timer */
+ case 0x9f: /* STPCLK# De-assertion Timer */
+ case 0xa0:
+ case 0xa1:
+ case 0xa2:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0xa3: /* SMRAM access control and Power supply control */
+ dev->pci_conf[addr] = val & 0xd0;
+ sis_5571_smm_recalc(dev);
+ break;
+
+ default:
+ break;
+ }
+ sis_5571_log("SiS5571: dev->pci_conf[%02x] = %02x\n", addr, val);
+}
+
+static uint8_t
+memory_pci_bridge_read(UNUSED(int func), int addr, void *priv)
+{
+ const sis_5571_t *dev = (sis_5571_t *) priv;
+
+ sis_5571_log("SiS5571: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]);
+ return dev->pci_conf[addr];
+}
+
+static void
+pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv)
+{
+ sis_5571_t *dev = (sis_5571_t *) priv;
+ switch (func) {
+ case 0: /* Bridge */
+ switch (addr) {
+ case 0x04: /* Command */
+ dev->pci_conf_sb[0][addr] |= val & 0x0f;
+ break;
+
+ case 0x06: /* Status */
+ dev->pci_conf_sb[0][addr] &= val;
+ break;
+
+ case 0x40: /* BIOS Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0x3f;
+ break;
+
+ case 0x41: /* INTA# Remapping Control Register */
+ case 0x42: /* INTB# Remapping Control Register */
+ case 0x43: /* INTC# Remapping Control Register */
+ case 0x44: /* INTD# Remapping Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0x8f;
+ pci_set_irq_routing((addr & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
+ break;
+
+ case 0x45:
+ dev->pci_conf_sb[0][addr] = val & 0xec;
+ switch ((val & 0xc0) >> 6) {
+ case 0:
+ cpu_set_isa_speed(7159091);
+ break;
+ case 1:
+ cpu_set_isa_pci_div(4);
+ break;
+ case 2:
+ cpu_set_isa_pci_div(3);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case 0x46:
+ dev->pci_conf_sb[0][addr] = val & 0xec;
+ break;
+
+ case 0x47: /* DMA Clock and Wait State Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0x3e;
+ break;
+
+ case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
+ case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
+ case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
+ case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5a:
+ case 0x5b:
+ case 0x5c:
+ case 0x5d:
+ case 0x5e:
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x5f:
+ dev->pci_conf_sb[0][addr] = val & 0x3f;
+ break;
+
+ case 0x60:
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x61: /* MIRQ Remapping Control Register */
+ dev->pci_conf_sb[0][addr] = val;
+ pci_set_mirq_routing(PCI_MIRQ0, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
+ break;
+
+ case 0x62: /* On-board Device DMA Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0x0f;
+ dma_set_drq((val & 0x07), 1);
+ break;
+
+ case 0x63: /* IDEIRQ Remapping Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0x8f;
+ if (val & 0x80) {
+ sff_set_irq_line(dev->ide_drive[0], val & 0x0f);
+ sff_set_irq_line(dev->ide_drive[1], val & 0x0f);
+ }
+ break;
+
+ case 0x64: /* GPIO Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0xef;
+ break;
+
+ case 0x65:
+ dev->pci_conf_sb[0][addr] = val & 0x1b;
+ break;
+
+ case 0x66: /* GPIO Output Mode Control Register */
+ case 0x67: /* GPIO Output Mode Control Register */
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x68: /* USBIRQ Remapping Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0x1b;
+ break;
+
+ case 0x69:
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x6a:
+ dev->pci_conf_sb[0][addr] = val & 0xfc;
+ break;
+
+ case 0x6b:
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x6c:
+ dev->pci_conf_sb[0][addr] = val & 0x03;
+ break;
+
+ case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */
+ case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ case 0x70:
+ dev->pci_conf_sb[0][addr] = val & 0xde;
+ break;
+
+ case 0x71: /* Type-F DMA Control Register */
+ dev->pci_conf_sb[0][addr] = val & 0xfe;
+ break;
+
+ case 0x72: /* SMI Triggered By IRQ/GPIO Control */
+ case 0x73: /* SMI Triggered By IRQ/GPIO Control */
+ dev->pci_conf_sb[0][addr] = (addr == 0x72) ? val & 0xfe : val;
+ break;
+
+ case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */
+ case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */
+ case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
+ case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
+ dev->pci_conf_sb[0][addr] = val;
+ break;
+
+ default:
+ break;
+ }
+ sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, val);
+ break;
+
+ case 1: /* IDE Controller */
+ switch (addr) {
+ case 0x04: /* Command low byte */
+ dev->pci_conf_sb[1][addr] = val & 0x05;
+ sis_5571_ide_handler(dev);
+ sis_5571_bm_handler(dev);
+ break;
+
+ case 0x07: /* Status high byte */
+ dev->pci_conf_sb[1][addr] &= val;
+ break;
+
+ case 0x09: /* Programming Interface Byte */
+ dev->pci_conf_sb[1][addr] = val & 0xcf;
+ sis_5571_ide_handler(dev);
+ break;
+
+ case 0x0d: /* Latency Time */
+ case 0x10: /* Primary Channel Base Address Register */
+ case 0x11: /* Primary Channel Base Address Register */
+ case 0x12: /* Primary Channel Base Address Register */
+ case 0x13: /* Primary Channel Base Address Register */
+ case 0x14: /* Primary Channel Base Address Register */
+ case 0x15: /* Primary Channel Base Address Register */
+ case 0x16: /* Primary Channel Base Address Register */
+ case 0x17: /* Primary Channel Base Address Register */
+ case 0x18: /* Secondary Channel Base Address Register */
+ case 0x19: /* Secondary Channel Base Address Register */
+ case 0x1a: /* Secondary Channel Base Address Register */
+ case 0x1b: /* Secondary Channel Base Address Register */
+ case 0x1c: /* Secondary Channel Base Address Register */
+ case 0x1d: /* Secondary Channel Base Address Register */
+ case 0x1e: /* Secondary Channel Base Address Register */
+ case 0x1f: /* Secondary Channel Base Address Register */
+ dev->pci_conf_sb[1][addr] = val;
+ sis_5571_ide_handler(dev);
+ break;
+
+ case 0x20: /* Bus Master IDE Control Register Base Address */
+ case 0x21: /* Bus Master IDE Control Register Base Address */
+ case 0x22: /* Bus Master IDE Control Register Base Address */
+ case 0x23: /* Bus Master IDE Control Register Base Address */
+ dev->pci_conf_sb[1][addr] = val;
+ sis_5571_bm_handler(dev);
+ break;
+
+ case 0x30: /* Expansion ROM Base Address */
+ case 0x31: /* Expansion ROM Base Address */
+ case 0x32: /* Expansion ROM Base Address */
+ case 0x33: /* Expansion ROM Base Address */
+ case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
+ case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
+ case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
+ case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
+ case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
+ case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
+ case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
+ case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
+ case 0x48: /* IDE Command Recovery Time Control */
+ case 0x49: /* IDE Command Active Time Control */
+ dev->pci_conf_sb[1][addr] = val;
+ break;
+
+ case 0x4a: /* IDE General Control Register 0 */
+ dev->pci_conf_sb[1][addr] = val & 0xaf;
+ sis_5571_ide_handler(dev);
+ break;
+
+ case 0x4b: /* IDE General Control register 1 */
+ case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
+ case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
+ case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
+ case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
+ dev->pci_conf_sb[1][addr] = val;
+ break;
+
+ default:
+ break;
+ }
+ sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", addr, val);
+ break;
+
+ case 2: /* USB Controller */
+ switch (addr) {
+ case 0x04: /* Command - Low Byte */
+ dev->pci_conf_sb[2][addr] = val;
+ ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1);
+ break;
+
+ case 0x05: /* Command - High Byte */
+ dev->pci_conf_sb[2][addr] = val & 0x03;
+ break;
+
+ case 0x06: /* Status - Low Byte */
+ dev->pci_conf_sb[2][addr] &= val & 0xc0;
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf_sb[2][addr] &= val;
+ break;
+
+ case 0x10: /* Memory Space Base Address Register */
+ case 0x11: /* Memory Space Base Address Register */
+ case 0x12: /* Memory Space Base Address Register */
+ case 0x13: /* Memory Space Base Address Register */
+ dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0x0f : 0xff);
+ ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1);
+ break;
+
+ case 0x14: /* IO Space Base Address Register */
+ case 0x15: /* IO Space Base Address Register */
+ case 0x16: /* IO Space Base Address Register */
+ case 0x17: /* IO Space Base Address Register */
+ case 0x3c: /* Interrupt Line */
+ dev->pci_conf_sb[2][addr] = val;
+ break;
+
+ default:
+ break;
+ }
+ sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] = %02x\n", addr, val);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static uint8_t
+pci_isa_bridge_read(int func, int addr, void *priv)
+{
+ const sis_5571_t *dev = (sis_5571_t *) priv;
+
+ switch (func) {
+ case 0:
+ sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[0][addr]);
+ return dev->pci_conf_sb[0][addr];
+ case 1:
+ sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[1][addr]);
+ return dev->pci_conf_sb[1][addr];
+ case 2:
+ sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[2][addr]);
+ return dev->pci_conf_sb[2][addr];
+
+ default:
+ return 0xff;
+ }
+}
+
+static void
+sis_5571_reset(void *priv)
+{
+ sis_5571_t *dev = (sis_5571_t *) priv;
+
+ /* Memory/PCI Bridge */
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x71;
+ dev->pci_conf[0x03] = 0x55;
+ dev->pci_conf[0x04] = 0xfd;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x9e] = 0xff;
+ dev->pci_conf[0x9f] = 0xff;
+ dev->pci_conf[0xa2] = 0xff;
+
+ /* PCI to ISA bridge */
+ dev->pci_conf_sb[0][0x00] = 0x39;
+ dev->pci_conf_sb[0][0x01] = 0x10;
+ dev->pci_conf_sb[0][0x02] = 0x08;
+ dev->pci_conf_sb[0][0x04] = 0xfd;
+ dev->pci_conf_sb[0][0x08] = 0x01;
+ dev->pci_conf_sb[0][0x0a] = 0x01;
+ dev->pci_conf_sb[0][0x0b] = 0x06;
+
+ /* IDE Controller */
+ dev->pci_conf_sb[1][0x00] = 0x39;
+ dev->pci_conf_sb[1][0x01] = 0x10;
+ dev->pci_conf_sb[1][0x02] = 0x13;
+ dev->pci_conf_sb[1][0x03] = 0x55;
+ dev->pci_conf_sb[1][0x08] = 0xc0;
+ dev->pci_conf_sb[1][0x0a] = 0x01;
+ dev->pci_conf_sb[1][0x0b] = 0x01;
+ dev->pci_conf_sb[1][0x0e] = 0x80;
+ dev->pci_conf_sb[1][0x4a] = 0x06;
+ sff_set_slot(dev->ide_drive[0], dev->sb_slot);
+ sff_set_slot(dev->ide_drive[1], dev->sb_slot);
+ sff_bus_master_reset(dev->ide_drive[0]);
+ sff_bus_master_reset(dev->ide_drive[1]);
+
+ /* USB Controller */
+ dev->pci_conf_sb[2][0x00] = 0x39;
+ dev->pci_conf_sb[2][0x01] = 0x10;
+ dev->pci_conf_sb[2][0x02] = 0x01;
+ dev->pci_conf_sb[2][0x03] = 0x70;
+ dev->pci_conf_sb[2][0x08] = 0xb0;
+ dev->pci_conf_sb[2][0x09] = 0x10;
+ dev->pci_conf_sb[2][0x0a] = 0x03;
+ dev->pci_conf_sb[2][0x0b] = 0xc0;
+ dev->pci_conf_sb[2][0x0e] = 0x80;
+ dev->pci_conf_sb[2][0x14] = 0x01;
+ dev->pci_conf_sb[2][0x3d] = 0x01;
+}
+
+static void
+sis_5571_close(void *priv)
+{
+ sis_5571_t *dev = (sis_5571_t *) priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+static void *
+sis_5571_init(UNUSED(const device_t *info))
+{
+ sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t));
+ memset(dev, 0x00, sizeof(sis_5571_t));
+
+ pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot);
+ pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot);
+
+ /* MIRQ */
+ pci_enable_mirq(0);
+
+ /* Port 92 & SMRAM */
+ dev->port_92 = device_add(&port_92_pci_device);
+ dev->smram = smram_add();
+
+ /* SFF IDE */
+ dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1);
+ dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2);
+
+ /* USB */
+ dev->usb = device_add(&usb_device);
+
+ sis_5571_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5571_device = {
+ .name = "SiS 5571",
+ .internal_name = "sis_5571",
+ .flags = DEVICE_PCI,
+ .local = 0,
+ .init = sis_5571_init,
+ .close = sis_5571_close,
+ .reset = sis_5571_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5572_usb.c b/src/chipset/sis_5572_usb.c
new file mode 100644
index 0000000000..250c325878
--- /dev/null
+++ b/src/chipset/sis_5572_usb.c
@@ -0,0 +1,323 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5572 USB controller.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+
+#ifdef ENABLE_SIS_5572_USB_LOG
+int sis_5572_usb_do_log = ENABLE_SIS_5572_USB_LOG;
+
+static void
+sis_5572_usb_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5572_usb_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5572_usb_log(fmt, ...)
+#endif
+
+typedef struct sis_5572_usb_t {
+ uint8_t rev;
+
+ uint8_t usb_unk_regs[256];
+ uint8_t pci_conf[256];
+
+ uint16_t usb_unk_base;
+
+ usb_t *usb;
+
+ sis_55xx_common_t *sis;
+} sis_5572_usb_t;
+
+/* SiS 5572 unknown I/O port (second USB PCI BAR). */
+static void
+sis_5572_usb_unk_write(uint16_t addr, uint8_t val, void *priv)
+{
+ sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
+
+ addr = (addr - dev->usb_unk_base) & 0x07;
+
+ sis_5572_usb_log("SiS 5572 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val);
+
+ dev->usb_unk_regs[addr] = val;
+}
+
+static uint8_t
+sis_5572_usb_unk_read(uint16_t addr, void *priv)
+{
+ const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
+ uint8_t ret = 0xff;
+
+ addr = (addr - dev->usb_unk_base) & 0x07;
+
+ ret = dev->usb_unk_regs[addr & 0x07];
+
+ sis_5572_usb_log("SiS 5572 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+void
+sis_5572_usb_write(int addr, uint8_t val, void *priv)
+{
+ sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
+
+ sis_5572_usb_log("SiS 5572 USB: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ if (dev->sis->usb_enabled) switch (addr) {
+ default:
+ break;
+
+ case 0x04: /* Command - Low Byte */
+ if (dev->rev == 0xb0)
+ dev->pci_conf[addr] = val & 0x47;
+ else
+ dev->pci_conf[addr] = val & 0x57;
+ if (dev->usb_unk_base != 0x0000) {
+ io_removehandler(dev->usb_unk_base, 0x0002,
+ sis_5572_usb_unk_read, NULL, NULL,
+ sis_5572_usb_unk_write, NULL, NULL, dev);
+ if (dev->pci_conf[0x04] & 0x01)
+ io_sethandler(dev->usb_unk_base, 0x0002,
+ sis_5572_usb_unk_read, NULL, NULL,
+ sis_5572_usb_unk_write, NULL, NULL, dev);
+ }
+ ohci_update_mem_mapping(dev->usb,
+ dev->pci_conf[0x11], dev->pci_conf[0x12],
+ dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02);
+ break;
+
+ case 0x05: /* Command - High Byte */
+ dev->pci_conf[addr] = val & 0x01;
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] &= ~(val & 0xf9);
+ break;
+
+ case 0x0d: /* Latency Timer */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x11 ... 0x13: /* Memory Space Base Address Register */
+ dev->pci_conf[addr] = val & ((addr == 0x11) ? 0xf0 : 0xff);
+ ohci_update_mem_mapping(dev->usb,
+ dev->pci_conf[0x11], dev->pci_conf[0x12],
+ dev->pci_conf[0x13], dev->pci_conf[4] & 0x02);
+ break;
+
+ case 0x14 ... 0x15: /* IO Space Base Address Register */
+ if (dev->rev == 0xb0) {
+ if (dev->usb_unk_base != 0x0000) {
+ io_removehandler(dev->usb_unk_base, 0x0002,
+ sis_5572_usb_unk_read, NULL, NULL,
+ sis_5572_usb_unk_write, NULL, NULL, dev);
+ }
+ dev->pci_conf[addr] = val;
+ dev->usb_unk_base = (dev->pci_conf[0x14] & 0xf8) |
+ (dev->pci_conf[0x15] << 8);
+ if (dev->usb_unk_base != 0x0000) {
+ io_sethandler(dev->usb_unk_base, 0x0002,
+ sis_5572_usb_unk_read, NULL, NULL,
+ sis_5572_usb_unk_write, NULL, NULL, dev);
+ }
+ }
+ break;
+
+ case 0x2c ... 0x2f:
+ if (dev->rev == 0x11)
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x3c: /* Interrupt Line */
+ dev->pci_conf[addr] = val;
+ break;
+ }
+}
+
+uint8_t
+sis_5572_usb_read(int addr, void *priv)
+{
+ const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
+ uint8_t ret = 0xff;
+
+ if (dev->sis->usb_enabled) {
+ ret = dev->pci_conf[addr];
+
+ sis_5572_usb_log("SiS 5572 USB: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+ }
+
+ return ret;
+}
+
+static void
+sis_5572_usb_reset(void *priv)
+{
+ sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x01;
+ dev->pci_conf[0x03] = 0x70;
+ dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00;
+ dev->pci_conf[0x06] = (dev->rev == 0xb0) ? 0x00 : 0x80;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = dev->rev;
+ dev->pci_conf[0x09] = 0x10;
+ dev->pci_conf[0x0a] = 0x03;
+ dev->pci_conf[0x0b] = 0x0c;
+ dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00;
+ dev->pci_conf[0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */;
+ dev->pci_conf[0x0f] = 0x00;
+ dev->pci_conf[0x10] = 0x00;
+ dev->pci_conf[0x11] = 0x00;
+ dev->pci_conf[0x12] = 0x00;
+ dev->pci_conf[0x13] = 0x00;
+ if (dev->rev == 0xb0) {
+ dev->pci_conf[0x14] = 0x01;
+ dev->pci_conf[0x15] = 0x00;
+ dev->pci_conf[0x16] = 0x00;
+ dev->pci_conf[0x17] = 0x00;
+ } else if (dev->rev == 0x11) {
+ dev->pci_conf[0x2c] = 0x00;
+ dev->pci_conf[0x2d] = 0x00;
+ dev->pci_conf[0x2e] = 0x00;
+ dev->pci_conf[0x2f] = 0x00;
+ }
+ dev->pci_conf[0x3c] = 0x00;
+ dev->pci_conf[0x3d] = PCI_INTA;
+ dev->pci_conf[0x3e] = 0x00;
+ dev->pci_conf[0x3f] = 0x00;
+
+ if (dev->rev == 0xb0) {
+ ohci_update_mem_mapping(dev->usb,
+ dev->pci_conf[0x11], dev->pci_conf[0x12],
+ dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02);
+
+ if (dev->usb_unk_base != 0x0000) {
+ io_removehandler(dev->usb_unk_base, 0x0002,
+ sis_5572_usb_unk_read, NULL, NULL,
+ sis_5572_usb_unk_write, NULL, NULL, dev);
+ }
+
+ dev->usb_unk_base = 0x0000;
+
+ memset(dev->usb_unk_regs, 0x00, sizeof(dev->usb_unk_regs));
+ }
+}
+
+static void
+sis_5572_usb_close(void *priv)
+{
+ sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_5572_usb_init(UNUSED(const device_t *info))
+{
+ sis_5572_usb_t *dev = (sis_5572_usb_t *) calloc(1, sizeof(sis_5572_usb_t));
+
+ dev->rev = info->local;
+
+ dev->sis = device_get_common_priv();
+
+ /* USB */
+ dev->usb = device_add(&usb_device);
+
+ sis_5572_usb_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5572_usb_device = {
+ .name = "SiS 5572 USB controller",
+ .internal_name = "sis_5572_usb",
+ .flags = DEVICE_PCI,
+ .local = 0xb0,
+ .init = sis_5572_usb_init,
+ .close = sis_5572_usb_close,
+ .reset = sis_5572_usb_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5582_usb_device = {
+ .name = "SiS 5582 USB controller",
+ .internal_name = "sis_5582_usb",
+ .flags = DEVICE_PCI,
+ .local = 0xe0,
+ .init = sis_5572_usb_init,
+ .close = sis_5572_usb_close,
+ .reset = sis_5572_usb_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5595_usb_device = {
+ .name = "SiS 5595 USB controller",
+ .internal_name = "sis_5595_usb",
+ .flags = DEVICE_PCI,
+ .local = 0x11,
+ .init = sis_5572_usb_init,
+ .close = sis_5572_usb_close,
+ .reset = sis_5572_usb_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5581.c b/src/chipset/sis_5581.c
new file mode 100644
index 0000000000..e2308c2d9e
--- /dev/null
+++ b/src/chipset/sis_5581.c
@@ -0,0 +1,184 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5581/5582 Pentium PCI/ISA Chipset.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/apm.h>
+#include <86box/acpi.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+
+#ifdef ENABLE_SIS_5581_LOG
+int sis_5581_do_log = ENABLE_SIS_5581_LOG;
+
+static void
+sis_5581_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5581_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5581_log(fmt, ...)
+#endif
+
+typedef struct sis_5581_t {
+ uint8_t nb_slot;
+ uint8_t sb_slot;
+
+ void *h2p;
+ void *p2i;
+ void *ide;
+ void *usb;
+
+ sis_55xx_common_t *sis;
+} sis_5581_t;
+
+static void
+sis_5581_write(int func, int addr, uint8_t val, void *priv)
+{
+ const sis_5581_t *dev = (sis_5581_t *) priv;
+
+ sis_5581_log("SiS 5581: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ if (func == 0x00)
+ sis_5581_host_to_pci_write(addr, val, dev->h2p);
+}
+
+static uint8_t
+sis_5581_read(int func, int addr, void *priv)
+{
+ const sis_5581_t *dev = (sis_5581_t *) priv;
+ uint8_t ret = 0xff;
+
+ if (func == 0x00)
+ ret = sis_5581_host_to_pci_read(addr, dev->h2p);
+
+ sis_5581_log("SiS 5581: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5582_write(int func, int addr, uint8_t val, void *priv)
+{
+ const sis_5581_t *dev = (sis_5581_t *) priv;
+
+ sis_5581_log("SiS 5582: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (func) {
+ case 0x00:
+ sis_5513_pci_to_isa_write(addr, val, dev->p2i);
+ break;
+ case 0x01:
+ sis_5513_ide_write(addr, val, dev->ide);
+ break;
+ case 0x02:
+ sis_5572_usb_write(addr, val, dev->usb);
+ break;
+ }
+}
+
+static uint8_t
+sis_5582_read(int func, int addr, void *priv)
+{
+ const sis_5581_t *dev = (sis_5581_t *) priv;
+ uint8_t ret = 0xff;
+
+ switch (func) {
+ case 0x00:
+ ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
+ break;
+ case 0x01:
+ ret = sis_5513_ide_read(addr, dev->ide);
+ break;
+ case 0x02:
+ ret = sis_5572_usb_read(addr, dev->usb);
+ break;
+ }
+
+ sis_5581_log("SiS 5582: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5581_close(void *priv)
+{
+ sis_5581_t *dev = (sis_5581_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_5581_init(UNUSED(const device_t *info))
+{
+ sis_5581_t *dev = (sis_5581_t *) calloc(1, sizeof(sis_5581_t));
+
+ /* Device 0: SiS 5581 */
+ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5581_read, sis_5581_write, dev, &dev->nb_slot);
+ /* Device 1: SiS 5582 */
+ pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5582_read, sis_5582_write, dev, &dev->sb_slot);
+
+ dev->sis = device_add(&sis_55xx_common_device);
+
+ dev->p2i = device_add_linked(&sis_5582_p2i_device, dev->sis);
+ dev->h2p = device_add_linked(&sis_5581_h2p_device, dev->sis);
+ dev->ide = device_add_linked(&sis_5582_ide_device, dev->sis);
+ dev->usb = device_add_linked(&sis_5582_usb_device, dev->sis);
+
+ return dev;
+}
+
+const device_t sis_5581_device = {
+ .name = "SiS 5581",
+ .internal_name = "sis_5581",
+ .flags = DEVICE_PCI,
+ .local = 0,
+ .init = sis_5581_init,
+ .close = sis_5581_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5581_h2p.c b/src/chipset/sis_5581_h2p.c
new file mode 100644
index 0000000000..30bd70bfea
--- /dev/null
+++ b/src/chipset/sis_5581_h2p.c
@@ -0,0 +1,552 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5581 Host to PCI bridge.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+
+#ifdef ENABLE_SIS_5581_HOST_TO_PCI_LOG
+int sis_5581_host_to_pci_do_log = ENABLE_SIS_5581_HOST_TO_PCI_LOG;
+
+static void
+sis_5581_host_to_pci_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5581_host_to_pci_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5581_host_to_pci_log(fmt, ...)
+#endif
+
+typedef struct {
+ uint8_t installed;
+ uint8_t code;
+ uint32_t phys_size;
+} ram_bank_t;
+
+typedef struct sis_5581_io_trap_t {
+ void *priv;
+ void *trap;
+ uint8_t flags, mask;
+ uint8_t *sts_reg, sts_mask;
+ uint16_t addr;
+} sis_5581_io_trap_t;
+
+typedef struct sis_5581_host_to_pci_t {
+ uint8_t pci_conf[256];
+ uint8_t states[7];
+
+ ram_bank_t ram_banks[3];
+
+ sis_5581_io_trap_t io_traps[10];
+
+ sis_55xx_common_t *sis;
+
+ smram_t *smram;
+} sis_5581_host_to_pci_t;
+
+static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b };
+
+static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */
+ 0x01000000, /* 16 MB */
+ 0x02000000, /* 32 MB */
+ 0x04000000, /* 64 MB */
+ 0x08000000, /* 128 MB */
+ 0x10000000, /* 256 MB */
+ 0x20000000 }; /* 512 MB */
+
+static void
+sis_5581_shadow_recalc(sis_5581_host_to_pci_t *dev)
+{
+ int state;
+ uint32_t base;
+
+ for (uint8_t i = 0x70; i <= 0x76; i++) {
+ if (i == 0x76) {
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
+ state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(0xf0000, 0x10000, state);
+ sis_5581_host_to_pci_log("000F0000-000FFFFF\n");
+ }
+ } else {
+ base = ((i & 0x07) << 15) + 0xc0000;
+
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
+ state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(base, 0x4000, state);
+ sis_5581_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+ }
+
+ if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
+ state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_both(base + 0x4000, 0x4000, state);
+ sis_5581_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
+ }
+ }
+
+ dev->states[i & 0x0f] = dev->pci_conf[i];
+ }
+
+ flushmmucache_nopc();
+}
+
+static void
+sis_5581_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val),
+ void *priv)
+{
+ sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv;
+ sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) trap->priv;
+
+ trap->sts_reg[0x04] |= trap->sts_mask;
+
+ if (trap->sts_reg[0x00] & trap->sts_mask)
+ acpi_sis5582_pmu_event(dev->sis->acpi);
+}
+
+static void
+sis_5581_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
+{
+ sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv;
+
+ if ((addr & trap->mask) == (trap->addr & trap->mask))
+ sis_5581_trap_io(size, addr, write, val, priv);
+}
+
+static void
+sis_5581_trap_update_devctl(sis_5581_host_to_pci_t *dev, uint8_t trap_id, uint8_t enable,
+ uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask,
+ uint16_t addr, uint16_t size)
+{
+ sis_5581_io_trap_t *trap = &dev->io_traps[trap_id];
+
+ /* Set up Device I/O traps dynamically. */
+ if (enable && !trap->trap) {
+ trap->priv = (void *) dev;
+ trap->flags = flags;
+ trap->mask = mask;
+ trap->addr = addr;
+ if (flags & 0x08)
+ trap->trap = io_trap_add(sis_5581_trap_io_mask, trap);
+ else
+ trap->trap = io_trap_add(sis_5581_trap_io, trap);
+ trap->sts_reg = sts_reg;
+ trap->sts_mask = sts_mask;
+ }
+
+ /* Remap I/O trap. */
+ io_trap_remap(trap->trap, enable, addr, size);
+}
+
+static void
+sis_5581_trap_update(void *priv)
+{
+ sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
+ uint8_t trap_id = 0;
+ uint8_t *fregs = dev->pci_conf;
+ uint16_t temp;
+ uint8_t mask;
+ uint8_t on;
+
+ on = fregs[0x9a];
+
+ temp = ((fregs[0x96] & 0x02) | (fregs[0x97] << 2)) & 0x03ff;
+ mask = ~((1 << ((fregs[0x96] >> 3) & 0x07)) - 1);
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x40, 0x08, mask, &(fregs[0x9c]), 0x40, temp, 0x80);
+
+ temp = fregs[0x98] | (fregs[0x99] << 8);
+ mask = 0xff;
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x20, 0x08, mask, &(fregs[0x9c]), 0x20, temp, 0x80);
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x378, 0x08);
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x278, 0x08);
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x08, 0x00, 0xff, &(fregs[0x9c]), 0x08, 0x3f8, 0x08);
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x04, 0x00, 0xff, &(fregs[0x9c]), 0x04, 0x2f8, 0x08);
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x02, 0x00, 0xff, &(fregs[0x9c]), 0x02, 0x1f0, 0x08);
+
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x01, 0x00, 0xff, &(fregs[0x9c]), 0x01, 0x170, 0x08);
+
+ on = fregs[0x9b];
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x064, 0x01);
+ sis_5581_trap_update_devctl(dev, trap_id++,
+ on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x060, 0x01);
+}
+
+static void
+sis_5581_smram_recalc(sis_5581_host_to_pci_t *dev)
+{
+ smram_disable_all();
+
+ switch (dev->pci_conf[0xa3] >> 6) {
+ case 0:
+ smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+ case 1:
+ smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+ case 2:
+ smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+ case 3:
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1);
+ break;
+
+ default:
+ break;
+ }
+
+ flushmmucache();
+}
+
+void
+sis_5581_host_to_pci_write(int addr, uint8_t val, void *priv)
+{
+ sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
+
+ sis_5581_host_to_pci_log("SiS 5581 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ default:
+ break;
+
+ case 0x04: /* Command - Low Byte */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfc) | (val & 0x03);
+ break;
+ case 0x05: /* Command - High Byte */
+ dev->pci_conf[addr] = val & 0x02;
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] &= ~(val & 0xb8);
+ break;
+
+ case 0x0d: /* Master latency timer */
+ case 0x50:
+ case 0x54:
+ case 0x56 ... 0x57:
+ case 0x59:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x51:
+ dev->pci_conf[addr] = val;
+ cpu_cache_ext_enabled = !!(val & 0x40);
+ cpu_update_waitstates();
+ break;
+
+ case 0x52:
+ dev->pci_conf[addr] = val & 0xeb;
+ break;
+
+ case 0x53:
+ case 0x55:
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x58:
+ dev->pci_conf[addr] = val & 0xfc;
+ break;
+
+ case 0x5a:
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+
+ case 0x60 ... 0x62:
+ dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0;
+ break;
+
+ case 0x63:
+ dev->pci_conf[addr] = dev->ram_banks[0].installed |
+ (dev->ram_banks[1].installed << 1) |
+ (dev->ram_banks[2].installed << 2);
+ break;
+
+ case 0x70 ... 0x75:
+ dev->pci_conf[addr] = val & 0xee;
+ sis_5581_shadow_recalc(dev);
+ break;
+ case 0x76:
+ dev->pci_conf[addr] = val & 0xe8;
+ sis_5581_shadow_recalc(dev);
+ break;
+
+ case 0x77: /* Characteristics of non-cacheable area */
+ dev->pci_conf[addr] = val & 0x0f;
+ break;
+
+ case 0x78: /* Allocation of Non-Cacheable area #1 */
+ case 0x79: /* NCA1REG2 */
+ case 0x7a: /* Allocation of Non-Cacheable area #2 */
+ case 0x7b: /* NCA2REG2 */
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x80: /* PCI master characteristics */
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x81:
+ dev->pci_conf[addr] = val & 0xde;
+ break;
+
+ case 0x82:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x83: /* CPU to PCI characteristics */
+ dev->pci_conf[addr] = val;
+ /* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */
+ break;
+
+ case 0x84 ... 0x86:
+ case 0x88 ... 0x8b:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x87: /* Miscellanea */
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+
+ case 0x8c ... 0x92:
+ case 0x9e ... 0xa2:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x93:
+ dev->pci_conf[addr] = val;
+ if (val & 0x02) {
+ dev->pci_conf[0x9d] |= 0x01;
+ if (dev->pci_conf[0x9b] & 0x01)
+ acpi_sis5582_pmu_event(dev->sis->acpi);
+ }
+ break;
+
+ case 0x94:
+ dev->pci_conf[addr] = val & 0xf8;
+ break;
+
+ case 0x95:
+ dev->pci_conf[addr] = val & 0xfb;
+ break;
+
+ case 0x96:
+ dev->pci_conf[addr] = val & 0xfb;
+ sis_5581_trap_update(dev);
+ break;
+ case 0x97 ... 0x9b:
+ dev->pci_conf[addr] = val;
+ sis_5581_trap_update(dev);
+ break;
+
+ case 0x9c ... 0x9d:
+ dev->pci_conf[addr] &= ~val;
+ break;
+
+ case 0xa3:
+ dev->pci_conf[addr] = val;
+ sis_5581_smram_recalc(dev);
+ break;
+ }
+}
+
+uint8_t
+sis_5581_host_to_pci_read(int addr, void *priv)
+{
+ const sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
+ uint8_t ret = 0xff;
+
+ ret = dev->pci_conf[addr];
+
+ sis_5581_host_to_pci_log("SiS 5581 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5581_host_to_pci_reset(void *priv)
+{
+ sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x97;
+ dev->pci_conf[0x03] = 0x55;
+ dev->pci_conf[0x04] = 0x05;
+ dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x02;
+ dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x0c] = 0x00;
+ dev->pci_conf[0x0d] = 0xff;
+ dev->pci_conf[0x0e] = dev->pci_conf[0x0f] = 0x00;
+ dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
+ dev->pci_conf[0x52] = 0x00;
+ dev->pci_conf[0x53] = 0x38;
+ dev->pci_conf[0x54] = 0x54;
+ dev->pci_conf[0x55] = 0x00;
+ dev->pci_conf[0x56] = 0x80;
+ dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
+ dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
+ dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
+ dev->pci_conf[0x62] = 0x00;
+ dev->pci_conf[0x63] = 0xff;
+ dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
+ dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
+ dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
+ dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
+ dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
+ dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
+ dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00;
+ dev->pci_conf[0x86] = dev->pci_conf[0x87] = 0x00;
+ dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00;
+ dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00;
+ dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
+ dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00;
+ dev->pci_conf[0x94] = dev->pci_conf[0x95] = 0x00;
+ dev->pci_conf[0x96] = dev->pci_conf[0x97] = 0x00;
+ dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00;
+ dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00;
+ dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00;
+ dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0xff;
+ dev->pci_conf[0xa0] = 0xff;
+ dev->pci_conf[0xa1] = 0x00;
+ dev->pci_conf[0xa2] = 0xff;
+ dev->pci_conf[0xa3] = 0x00;
+
+ cpu_cache_ext_enabled = 0;
+ cpu_update_waitstates();
+
+ sis_5581_shadow_recalc(dev);
+
+ sis_5581_trap_update(dev);
+
+ sis_5581_smram_recalc(dev);
+}
+
+static void
+sis_5581_host_to_pci_close(void *priv)
+{
+ sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+static void *
+sis_5581_host_to_pci_init(UNUSED(const device_t *info))
+{
+ sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) calloc(1, sizeof(sis_5581_host_to_pci_t));
+ uint32_t total_mem = mem_size << 10;
+ ram_bank_t *rb;
+
+ dev->sis = device_get_common_priv();
+
+ /* Calculate the physical RAM banks. */
+ for (uint8_t i = 0; i < 3; i++) {
+ rb = &(dev->ram_banks[i]);
+ uint32_t size = 0x00000000;
+ uint8_t index = 0;
+ for (int8_t j = 6; j >= 0; j--) {
+ uint32_t *bs = &(bank_sizes[j]);
+ if (*bs <= total_mem) {
+ size = *bs;
+ index = j;
+ break;
+ }
+ }
+ if (size != 0x00000000) {
+ rb->installed = 1;
+ rb->code = bank_codes[index];
+ rb->phys_size = size;
+ total_mem -= size;
+ } else
+ rb->installed = 0;
+ }
+
+ /* SMRAM */
+ dev->smram = smram_add();
+
+ sis_5581_host_to_pci_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5581_h2p_device = {
+ .name = "SiS 5581 Host to PCI bridge",
+ .internal_name = "sis_5581_host_to_pci",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5581_host_to_pci_init,
+ .close = sis_5581_host_to_pci_close,
+ .reset = sis_5581_host_to_pci_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5591.c b/src/chipset/sis_5591.c
new file mode 100644
index 0000000000..969fcb8dd0
--- /dev/null
+++ b/src/chipset/sis_5591.c
@@ -0,0 +1,210 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5591/5592 Pentium PCI/ISA Chipset.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/apm.h>
+#include <86box/acpi.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+
+#ifdef ENABLE_SIS_5591_LOG
+int sis_5591_do_log = ENABLE_SIS_5591_LOG;
+
+static void
+sis_5591_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5591_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5591_log(fmt, ...)
+#endif
+
+typedef struct sis_5591_t {
+ uint8_t nb_slot;
+ uint8_t sb_slot;
+
+ void *h2p;
+ void *p2i;
+ void *ide;
+ void *usb;
+ void *pmu;
+
+ sis_55xx_common_t *sis;
+} sis_5591_t;
+
+static void
+sis_5591_write(int func, int addr, uint8_t val, void *priv)
+{
+ const sis_5591_t *dev = (sis_5591_t *) priv;
+
+ sis_5591_log("SiS 5591: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ if (func == 0x00)
+ sis_5591_host_to_pci_write(addr, val, dev->h2p);
+ else if (func == 0x01)
+ sis_5513_ide_write(addr, val, dev->ide);
+}
+
+static uint8_t
+sis_5591_read(int func, int addr, void *priv)
+{
+ const sis_5591_t *dev = (sis_5591_t *) priv;
+ uint8_t ret = 0xff;
+
+ if (func == 0x00)
+ ret = sis_5591_host_to_pci_read(addr, dev->h2p);
+ else if (func == 0x01)
+ ret = sis_5513_ide_read(addr, dev->ide);
+
+ sis_5591_log("SiS 5591: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5595_write(int func, int addr, uint8_t val, void *priv)
+{
+ const sis_5591_t *dev = (sis_5591_t *) priv;
+
+ sis_5591_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (func) {
+ case 0x00:
+ sis_5513_pci_to_isa_write(addr, val, dev->p2i);
+ break;
+ case 0x01:
+ sis_5595_pmu_write(addr, val, dev->pmu);
+ break;
+ case 0x02:
+ sis_5572_usb_write(addr, val, dev->usb);
+ break;
+ }
+}
+
+static uint8_t
+sis_5595_read(int func, int addr, void *priv)
+{
+ const sis_5591_t *dev = (sis_5591_t *) priv;
+ uint8_t ret = 0xff;
+
+ switch (func) {
+ case 0x00:
+ ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
+ break;
+ case 0x01:
+ ret = sis_5595_pmu_read(addr, dev->pmu);
+ break;
+ case 0x02:
+ ret = sis_5572_usb_read(addr, dev->usb);
+ break;
+ }
+
+ sis_5591_log("SiS 5592: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5591_close(void *priv)
+{
+ sis_5591_t *dev = (sis_5591_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_5591_init(UNUSED(const device_t *info))
+{
+ sis_5591_t *dev = (sis_5591_t *) calloc(1, sizeof(sis_5591_t));
+
+ /* Device 0: SiS 5591 */
+ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5591_read, sis_5591_write, dev, &dev->nb_slot);
+ /* Device 1: SiS 5595 */
+ pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot);
+
+ dev->sis = device_add(&sis_55xx_common_device);
+
+ dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis);
+ if (info->local)
+ dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis);
+ else
+ dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis);
+ dev->h2p = device_add_linked(&sis_5591_h2p_device, dev->sis);
+ dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis);
+ if (info->local)
+ dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis);
+ else
+ dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
+
+ return dev;
+}
+
+const device_t sis_5591_1997_device = {
+ .name = "SiS 5591 (1997)",
+ .internal_name = "sis_5591_1997",
+ .flags = DEVICE_PCI,
+ .local = 1,
+ .init = sis_5591_init,
+ .close = sis_5591_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5591_device = {
+ .name = "SiS 5591",
+ .internal_name = "sis_5591",
+ .flags = DEVICE_PCI,
+ .local = 0,
+ .init = sis_5591_init,
+ .close = sis_5591_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5591_h2p.c b/src/chipset/sis_5591_h2p.c
new file mode 100644
index 0000000000..8fcbeeb6f7
--- /dev/null
+++ b/src/chipset/sis_5591_h2p.c
@@ -0,0 +1,493 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5591 Host to PCI bridge.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+#include <86box/agpgart.h>
+
+#ifdef ENABLE_SIS_5591_HOST_TO_PCI_LOG
+int sis_5591_host_to_pci_do_log = ENABLE_SIS_5591_HOST_TO_PCI_LOG;
+
+static void
+sis_5591_host_to_pci_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5591_host_to_pci_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5591_host_to_pci_log(fmt, ...)
+#endif
+
+typedef struct {
+ uint8_t installed;
+ uint8_t code;
+ uint32_t phys_size;
+} ram_bank_t;
+
+typedef struct sis_5591_host_to_pci_t {
+ uint8_t pci_conf[256];
+
+ uint8_t states[7];
+ uint8_t states_bus[7];
+
+ ram_bank_t ram_banks[3];
+
+ sis_55xx_common_t *sis;
+
+ smram_t *smram;
+
+ agpgart_t *agpgart;
+} sis_5591_host_to_pci_t;
+
+static uint8_t bank_codes[6] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a };
+
+static uint32_t bank_sizes[6] = { 0x00800000, /* 8 MB */
+ 0x01000000, /* 16 MB */
+ 0x02000000, /* 32 MB */
+ 0x04000000, /* 64 MB */
+ 0x08000000, /* 128 MB */
+ 0x10000000 }; /* 256 MB */
+
+static void
+sis_5591_shadow_recalc(sis_5591_host_to_pci_t *dev)
+{
+ uint32_t base;
+ uint32_t state;
+ uint8_t val;
+
+ for (uint8_t i = 0x70; i <= 0x76; i++) {
+ if (i == 0x76) {
+ val = dev->pci_conf[i];
+ if ((dev->states[i & 0x0f] ^ val) & 0xa0) {
+ state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_cpu_both(0xf0000, 0x10000, state);
+ sis_5591_host_to_pci_log("000F0000-000FFFFF\n");
+
+ dev->states[i & 0x0f] = val;
+ }
+
+ if (!(dev->pci_conf[0x76] & 0x08))
+ val &= 0x5f;
+ if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) {
+ state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_bus_both(0xf0000, 0x10000, state);
+ sis_5591_host_to_pci_log("000F0000-000FFFFF\n");
+
+ dev->states_bus[i & 0x0f] = val;
+ }
+ } else {
+ base = ((i & 0x07) << 15) + 0xc0000;
+
+ val = dev->pci_conf[i];
+ if ((dev->states[i & 0x0f] ^ val) & 0xa0) {
+ state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_cpu_both(base, 0x4000, state);
+ sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+
+ dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0x0f) | (val & 0xf0);
+ }
+ if ((dev->states[i & 0x0f] ^ val) & 0x0a) {
+ state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_cpu_both(base + 0x4000, 0x4000, state);
+ sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
+
+ dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0xf0) | (val & 0x0f);
+ }
+
+ if (!(dev->pci_conf[0x76] & 0x08))
+ val &= 0x55;
+ if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) {
+ state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_bus_both(base, 0x4000, state);
+ sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+
+ dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0x0f) | (val & 0xf0);
+ }
+ if ((dev->states_bus[i & 0x0f] ^ val) & 0x0a) {
+ state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ mem_set_mem_state_bus_both(base + 0x4000, 0x4000, state);
+ sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
+
+ dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0xf0) | (val & 0x0f);
+ }
+ }
+ }
+
+ flushmmucache_nopc();
+}
+
+static void
+sis_5591_smram_recalc(sis_5591_host_to_pci_t *dev)
+{
+ smram_disable_all();
+
+ switch (dev->pci_conf[0x68] >> 6) {
+ case 0:
+ smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
+ break;
+ case 1:
+ smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
+ break;
+ case 2:
+ smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
+ break;
+ case 3:
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x68] & 0x10, 1);
+ break;
+
+ default:
+ break;
+ }
+
+ flushmmucache();
+}
+
+static void
+sis_5591_mask_bar(uint8_t *regs, void *agpgart)
+{
+ uint32_t bar;
+ uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x00000000 } ;
+
+ /* Make sure the aperture's base is aligned to its size. */
+ bar = (regs[0x13] << 24) | (regs[0x12] << 16);
+ bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000);
+ regs[0x12] = (bar >> 16) & 0xff;
+ regs[0x13] = (bar >> 24) & 0xff;
+
+ if (!agpgart)
+ return;
+
+ /* Map aperture and GART. */
+ agpgart_set_aperture(agpgart,
+ bar,
+ sizes[(regs[0x94] >> 4) & 0x07],
+ !!(regs[0x94] & 0x02));
+ if (regs[0x94] & 0x01)
+ agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24));
+ else
+ agpgart_set_gart(agpgart, 0x00000000);
+}
+
+void
+sis_5591_host_to_pci_write(int addr, uint8_t val, void *priv)
+{
+ sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
+
+ sis_5591_host_to_pci_log("SiS 5591 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ default:
+ break;
+
+ case 0x04: /* Command - Low Byte */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
+ break;
+ case 0x05: /* Command - High Byte */
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] &= ~(val & 0xf0);
+ break;
+
+ case 0x12:
+ dev->pci_conf[addr] = val & 0xc0;
+ sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+ case 0x13:
+ dev->pci_conf[addr] = val;
+ sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+
+ case 0x51:
+ dev->pci_conf[addr] = val;
+ cpu_cache_ext_enabled = !!(val & 0x80);
+ cpu_update_waitstates();
+ break;
+
+ case 0x60 ... 0x62:
+ dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0;
+ break;
+
+ case 0x63:
+ dev->pci_conf[addr] = dev->ram_banks[0].installed |
+ (dev->ram_banks[1].installed << 1) |
+ (dev->ram_banks[2].installed << 2);
+ break;
+
+ case 0x68:
+ dev->pci_conf[addr] = val;
+ sis_5591_smram_recalc(dev);
+ break;
+
+ case 0x70 ... 0x75:
+ dev->pci_conf[addr] = val & 0xee;
+ sis_5591_shadow_recalc(dev);
+ break;
+ case 0x76:
+ dev->pci_conf[addr] = val & 0xe8;
+ sis_5591_shadow_recalc(dev);
+ break;
+
+ case 0x0d: /* Master latency timer */
+ case 0x50:
+ case 0x52:
+ case 0x54 ... 0x5a:
+ case 0x5c ... 0x5f:
+ case 0x64 ... 0x65:
+ case 0x69 ... 0x6c:
+ case 0x77 ... 0x7b:
+ case 0x80 ... 0x8d:
+ case 0x90:
+ case 0x97 ... 0xab:
+ case 0xb0:
+ case 0xc8 ... 0xcb:
+ case 0xd4 ... 0xda:
+ case 0xe0 ... 0xe3:
+ case 0xef:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x91 ... 0x93:
+ dev->pci_conf[addr] = val;
+ sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+ case 0x94:
+ dev->pci_conf[addr] = val & 0x7f;
+ sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+
+ case 0xb2:
+ dev->pci_conf[addr] &= ~(val & 0x01);
+ break;
+ }
+}
+
+uint8_t
+sis_5591_host_to_pci_read(int addr, void *priv)
+{
+ const sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
+ uint8_t ret = 0xff;
+
+ ret = dev->pci_conf[addr];
+
+ sis_5591_host_to_pci_log("SiS 5591 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5591_host_to_pci_reset(void *priv)
+{
+ sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x91;
+ dev->pci_conf[0x03] = 0x55;
+ dev->pci_conf[0x04] = 0x05;
+ dev->pci_conf[0x05] = 0x00;
+ dev->pci_conf[0x06] = 0x10;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x02;
+ dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x0c] = 0x00;
+ dev->pci_conf[0x0d] = 0xff;
+ dev->pci_conf[0x0e] = 0x80;
+ dev->pci_conf[0x0f] = 0x00;
+ dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00;
+ dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00;
+ dev->pci_conf[0x34] = 0xc0;
+ dev->pci_conf[0x50] = 0x00;
+ dev->pci_conf[0x51] = 0x18;
+ dev->pci_conf[0x52] = dev->pci_conf[0x54] = 0x00;
+ dev->pci_conf[0x55] = 0x0e;
+ dev->pci_conf[0x56] = 0x40;
+ dev->pci_conf[0x57] = 0x00;
+ dev->pci_conf[0x58] = 0x50;
+ dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
+ dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00;
+ dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00;
+ dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
+ dev->pci_conf[0x62] = 0x00;
+ dev->pci_conf[0x63] = 0xff;
+ dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
+ dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00;
+ dev->pci_conf[0x6c] = 0x00;
+ dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
+ dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
+ dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
+ dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
+ dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
+ dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
+ dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff;
+ dev->pci_conf[0x86] = 0xff;
+ dev->pci_conf[0x87] = 0x00;
+ dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00;
+ dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00;
+ dev->pci_conf[0x8c] = dev->pci_conf[0x8d] = 0x00;
+ dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
+ dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00;
+ dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00;
+ dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00;
+ dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00;
+ dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00;
+ dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0x00;
+ dev->pci_conf[0xa0] = dev->pci_conf[0xa1] = 0x00;
+ dev->pci_conf[0xa2] = dev->pci_conf[0xa3] = 0x00;
+ dev->pci_conf[0xa4] = dev->pci_conf[0xa5] = 0x00;
+ dev->pci_conf[0xa6] = dev->pci_conf[0xa7] = 0x00;
+ dev->pci_conf[0xa8] = dev->pci_conf[0xa9] = 0x00;
+ dev->pci_conf[0xaa] = dev->pci_conf[0xab] = 0x00;
+ dev->pci_conf[0xb0] = dev->pci_conf[0xb2] = 0x00;
+ dev->pci_conf[0xc0] = 0x02;
+ dev->pci_conf[0xc1] = 0x00;
+ dev->pci_conf[0xc2] = 0x10;
+ dev->pci_conf[0xc3] = 0x00;
+ dev->pci_conf[0xc4] = 0x03;
+ dev->pci_conf[0xc5] = 0x02;
+ dev->pci_conf[0xc6] = 0x00;
+ dev->pci_conf[0xc7] = 0x1f;
+ dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00;
+ dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00;
+ dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00;
+ dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00;
+ dev->pci_conf[0xd8] = dev->pci_conf[0xd9] = 0x00;
+ dev->pci_conf[0xda] = 0x00;
+ dev->pci_conf[0xe0] = dev->pci_conf[0xe1] = 0x00;
+ dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00;
+ dev->pci_conf[0xef] = 0x00;
+
+ sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
+
+ cpu_cache_ext_enabled = 0;
+ cpu_update_waitstates();
+
+ sis_5591_shadow_recalc(dev);
+
+ sis_5591_smram_recalc(dev);
+}
+
+static void
+sis_5591_host_to_pci_close(void *priv)
+{
+ sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+static void *
+sis_5591_host_to_pci_init(UNUSED(const device_t *info))
+{
+ sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) calloc(1, sizeof(sis_5591_host_to_pci_t));
+ uint32_t total_mem = mem_size << 10;
+ ram_bank_t *rb;
+
+ dev->sis = device_get_common_priv();
+
+ /* Calculate the physical RAM banks. */
+ for (uint8_t i = 0; i < 3; i++) {
+ rb = &(dev->ram_banks[i]);
+ uint32_t size = 0x00000000;
+ uint8_t index = 0;
+ for (int8_t j = 5; j >= 0; j--) {
+ uint32_t *bs = &(bank_sizes[j]);
+ if (*bs <= total_mem) {
+ size = *bs;
+ index = j;
+ break;
+ }
+ }
+ if (size != 0x00000000) {
+ rb->installed = 1;
+ rb->code = bank_codes[index];
+ rb->phys_size = size;
+ total_mem -= size;
+ } else
+ rb->installed = 0;
+ }
+
+ /* SMRAM */
+ dev->smram = smram_add();
+
+ device_add(&sis_5xxx_agp_device);
+ dev->agpgart = device_add(&agpgart_device);
+
+ sis_5591_host_to_pci_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5591_h2p_device = {
+ .name = "SiS 5591 Host to PCI bridge",
+ .internal_name = "sis_5591_host_to_pci",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5591_host_to_pci_init,
+ .close = sis_5591_host_to_pci_close,
+ .reset = sis_5591_host_to_pci_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5595_pmu.c b/src/chipset/sis_5595_pmu.c
new file mode 100644
index 0000000000..de351ad7c7
--- /dev/null
+++ b/src/chipset/sis_5595_pmu.c
@@ -0,0 +1,454 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 5572 USB controller.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+
+#ifdef ENABLE_SIS_5595_PMU_LOG
+int sis_5595_pmu_do_log = ENABLE_SIS_5595_PMU_LOG;
+
+static void
+sis_5595_pmu_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5595_pmu_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5595_pmu_log(fmt, ...)
+#endif
+
+typedef struct sis_5595_pmu_io_trap_t {
+ void *priv;
+ void *trap;
+ uint8_t flags, mask;
+ uint8_t *sts_reg, sts_mask;
+ uint16_t addr;
+} sis_5595_pmu_io_trap_t;
+
+typedef struct sis_5595_pmu_t {
+ uint8_t is_1997;
+
+ uint8_t pci_conf[256];
+
+ sis_5595_pmu_io_trap_t io_traps[22];
+
+ sis_55xx_common_t *sis;
+} sis_5595_pmu_t;
+
+static void
+sis_5595_pmu_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val),
+ void *priv)
+{
+ sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv;
+
+ trap->sts_reg[0x04] |= trap->sts_mask;
+
+ if (trap->sts_reg[0x00] & trap->sts_mask)
+ acpi_sis5595_pmu_event(dev->sis->acpi);
+
+ if (trap->sts_reg[0x20] & trap->sts_mask)
+ acpi_update_irq(dev->sis->acpi);
+}
+
+static void
+sis_5595_pmu_trap_io_ide(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
+{
+ sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
+
+ /* IDE traps are per drive, not per channel. */
+ if (ide_drives[trap->flags & 0x03]->selected)
+ sis_5595_pmu_trap_io(size, addr, write, val, priv);
+}
+
+static void
+sis_5595_pmu_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
+{
+ sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
+
+ if ((addr & trap->mask) == (trap->addr & trap->mask))
+ sis_5595_pmu_trap_io(size, addr, write, val, priv);
+}
+
+static void
+sis_5595_pmu_trap_io_ide_bm(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
+{
+ sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv;
+
+ if (trap->flags & 0x01) {
+ dev->pci_conf[0x67] |= 0x01;
+ dev->pci_conf[0x64] |= 0x08;
+ } else {
+ dev->pci_conf[0x67] |= 0x02;
+ dev->pci_conf[0x64] |= 0x10;
+ }
+ acpi_sis5595_pmu_event(dev->sis->acpi);
+}
+
+static void
+sis_5595_pmu_trap_update_devctl(sis_5595_pmu_t *dev, uint8_t trap_id, uint8_t enable,
+ uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask,
+ uint16_t addr, uint16_t size)
+{
+ sis_5595_pmu_io_trap_t *trap = &dev->io_traps[trap_id];
+
+ /* Set up Device I/O traps dynamically. */
+ if (enable && !trap->trap) {
+ trap->priv = (void *) dev;
+ trap->flags = flags;
+ trap->mask = mask;
+ trap->addr = addr;
+ if (flags & 0x10)
+ trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide_bm, trap);
+ else if (flags & 0x08)
+ trap->trap = io_trap_add(sis_5595_pmu_trap_io_mask, trap);
+ else if (flags & 0x04)
+ trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide, trap);
+ else
+ trap->trap = io_trap_add(sis_5595_pmu_trap_io, trap);
+ trap->sts_reg = sts_reg;
+ trap->sts_mask = sts_mask;
+ }
+
+ /* Remap I/O trap. */
+ io_trap_remap(trap->trap, enable, addr, size);
+}
+
+static void
+sis_5595_pmu_trap_update(void *priv)
+{
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
+ uint8_t trap_id = 0;
+ uint8_t *fregs = dev->pci_conf;
+ uint16_t temp;
+ uint8_t mask;
+ uint8_t on;
+
+ temp = (fregs[0x7e] | (fregs[0x7f] << 8)) & 0xffe0;
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ fregs[0x7e] & 0x08, 0x10, 0xff, NULL, 0xff, temp, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ fregs[0x7e] & 0x04, 0x10, 0xff, NULL, 0xff, temp + 8, 0x08);
+
+ on = fregs[0x63] | fregs[0x83];
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x02, 0x04, 0xff, &(fregs[0x63]), 0x02, 0x1f0, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x01, 0x06, 0xff, &(fregs[0x63]), 0x01, 0x170, 0x08);
+
+ on = fregs[0x62] | fregs[0x82];
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x064, 0x01);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x060, 0x01);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x40, 0x00, 0xff, &(fregs[0x62]), 0x40, 0x3f8, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x20, 0x00, 0xff, &(fregs[0x62]), 0x20, 0x2f8, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x378, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x278, 0x08);
+
+ temp = (fregs[0x5c] | (fregs[0x5d] << 8)) & 0x03ff;
+ mask = fregs[0x5d] >> 2;
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x04, 0x08, mask, &(fregs[0x62]), 0x04, temp, 0x40);
+
+ temp = fregs[0x5e] | (fregs[0x5f] << 8);
+
+ if (dev->is_1997) {
+ mask = fregs[0x4d] & 0x1f;
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x20);
+ } else {
+ mask = fregs[0x4d];
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x100);
+ }
+
+ on = fregs[0x61] | fregs[0x81];
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x40, 0x00, 0xff, &(fregs[0x61]), 0x40, 0x3b0, 0x30);
+
+ switch ((fregs[0x4c] >> 6) & 0x03) {
+ case 0x00:
+ temp = 0xf40;
+ break;
+ case 0x01:
+ temp = 0xe80;
+ break;
+ case 0x02:
+ temp = 0x604;
+ break;
+ default:
+ temp = 0x530;
+ break;
+ }
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x10, 0x00, 0xff, &(fregs[0x61]), 0x10, temp, 0x08);
+
+ switch ((fregs[0x4c] >> 4) & 0x03) {
+ case 0x00:
+ temp = 0x280;
+ break;
+ case 0x01:
+ temp = 0x260;
+ break;
+ case 0x02:
+ temp = 0x240;
+ break;
+ default:
+ temp = 0x220;
+ break;
+ }
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x08, 0x00, 0xff, &(fregs[0x61]), 0x08, temp, 0x14);
+
+ switch ((fregs[0x4c] >> 2) & 0x03) {
+ case 0x00:
+ temp = 0x330;
+ break;
+ case 0x01:
+ temp = 0x320;
+ break;
+ case 0x02:
+ temp = 0x310;
+ break;
+ default:
+ temp = 0x300;
+ break;
+ }
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x04, 0x00, 0xff, &(fregs[0x61]), 0x04, temp, 0x04);
+
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x200, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x388, 0x04);
+
+ on = fregs[0x60] | fregs[0x80];
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x3f0, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x370, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x10, 0x05, 0xff, &(fregs[0x60]), 0x10, 0x1f0, 0x08);
+ sis_5595_pmu_trap_update_devctl(dev, trap_id++,
+ on & 0x08, 0x07, 0xff, &(fregs[0x60]), 0x08, 0x170, 0x08);
+}
+
+void
+sis_5595_pmu_write(int addr, uint8_t val, void *priv)
+{
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
+
+ sis_5595_pmu_log("SiS 5595 PMU: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ if (dev->sis->usb_enabled) switch (addr) {
+ default:
+ break;
+
+ case 0x40 ... 0x4b:
+ case 0x50 ... 0x5b:
+ case 0x68 ... 0x7b:
+ case 0x7d:
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x4c ... 0x4d:
+ case 0x5c ... 0x63:
+ case 0x7e ... 0x7f:
+ case 0x80 ... 0x83:
+ dev->pci_conf[addr] = val;
+ sis_5595_pmu_trap_update(dev);
+ break;
+ case 0x64 ... 0x67:
+ dev->pci_conf[addr] &= ~val;
+ break;
+ case 0x7c:
+ dev->pci_conf[addr] = val;
+ if (val & 0x02) {
+ dev->pci_conf[0x64] |= 0x04;
+ if (dev->pci_conf[0x60] & 0x04)
+ acpi_sis5595_pmu_event(dev->sis->acpi);
+ }
+ break;
+ }
+}
+
+uint8_t
+sis_5595_pmu_read(int addr, void *priv)
+{
+ const sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
+ uint8_t ret = 0xff;
+
+ ret = dev->pci_conf[addr];
+
+ sis_5595_pmu_log("SiS 5595 PMU: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5595_pmu_reset(void *priv)
+{
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x09;
+ dev->pci_conf[0x03] = 0x00;
+ dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00;
+ dev->pci_conf[0x06] = 0x00;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = dev->pci_conf[0x09] = 0x00;
+ dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0xff;
+ dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00;
+ dev->pci_conf[0x0e] = 0x80;
+ dev->pci_conf[0x0f] = 0x00;
+ dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00;
+ dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00;
+ dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00;
+ dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00;
+ dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00;
+ dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00;
+ dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00;
+ dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00;
+ dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
+ dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00;
+ dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00;
+ dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00;
+ dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00;
+ dev->pci_conf[0x5a] = dev->pci_conf[0x5b] = 0x00;
+ dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00;
+ dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00;
+ dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
+ dev->pci_conf[0x62] = dev->pci_conf[0x63] = 0x00;
+ dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
+ dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
+ dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00;
+ dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00;
+ dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00;
+ dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
+ dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
+ dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
+ dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
+ dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
+ dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00;
+ dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00;
+ dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
+ dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
+
+ sis_5595_pmu_trap_update(dev);
+ acpi_update_irq(dev->sis->acpi);
+}
+
+static void
+sis_5595_pmu_close(void *priv)
+{
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_5595_pmu_init(UNUSED(const device_t *info))
+{
+ sis_5595_pmu_t *dev = (sis_5595_pmu_t *) calloc(1, sizeof(sis_5595_pmu_t));
+
+ dev->sis = device_get_common_priv();
+ dev->sis->pmu_regs = dev->pci_conf;
+
+ dev->is_1997 = info->local;
+
+ sis_5595_pmu_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5595_1997_pmu_device = {
+ .name = "SiS 5595 (1997) PMU",
+ .internal_name = "sis_5595_1997_pmu",
+ .flags = DEVICE_PCI,
+ .local = 0x01,
+ .init = sis_5595_pmu_init,
+ .close = sis_5595_pmu_close,
+ .reset = sis_5595_pmu_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5595_pmu_device = {
+ .name = "SiS 5595 PMU",
+ .internal_name = "sis_5595_pmu",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5595_pmu_init,
+ .close = sis_5595_pmu_close,
+ .reset = sis_5595_pmu_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_55xx.c b/src/chipset/sis_55xx.c
new file mode 100644
index 0000000000..2cad21f222
--- /dev/null
+++ b/src/chipset/sis_55xx.c
@@ -0,0 +1,96 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS 55xx common structure.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+
+#ifdef ENABLE_SIS_55XX_COMMON_LOG
+int sis_55xx_common_do_log = ENABLE_SIS_55XX_COMMON_LOG;
+
+static void
+sis_55xx_common_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_55xx_common_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_55xx_common_log(fmt, ...)
+#endif
+
+static void
+sis_55xx_common_close(void *priv)
+{
+ sis_55xx_common_t *dev = (sis_55xx_common_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_55xx_common_init(UNUSED(const device_t *info))
+{
+ sis_55xx_common_t *dev = (sis_55xx_common_t *) calloc(1, sizeof(sis_55xx_common_t));
+
+ return dev;
+}
+
+const device_t sis_55xx_common_device = {
+ .name = "SiS 55xx Common Structure",
+ .internal_name = "sis_55xx_common",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_55xx_common_init,
+ .close = sis_55xx_common_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5600.c b/src/chipset/sis_5600.c
new file mode 100644
index 0000000000..ed7384740a
--- /dev/null
+++ b/src/chipset/sis_5600.c
@@ -0,0 +1,210 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS (5)600 Pentium PCI/ISA Chipset.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/apm.h>
+#include <86box/acpi.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+
+#ifdef ENABLE_SIS_5600_LOG
+int sis_5600_do_log = ENABLE_SIS_5600_LOG;
+
+static void
+sis_5600_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5600_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5600_log(fmt, ...)
+#endif
+
+typedef struct sis_5600_t {
+ uint8_t nb_slot;
+ uint8_t sb_slot;
+
+ void *h2p;
+ void *p2i;
+ void *ide;
+ void *usb;
+ void *pmu;
+
+ sis_55xx_common_t *sis;
+} sis_5600_t;
+
+static void
+sis_5600_write(int func, int addr, uint8_t val, void *priv)
+{
+ const sis_5600_t *dev = (sis_5600_t *) priv;
+
+ sis_5600_log("SiS 5600: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ if (func == 0x00)
+ sis_5600_host_to_pci_write(addr, val, dev->h2p);
+ else if (func == 0x01)
+ sis_5513_ide_write(addr, val, dev->ide);
+}
+
+static uint8_t
+sis_5600_read(int func, int addr, void *priv)
+{
+ const sis_5600_t *dev = (sis_5600_t *) priv;
+ uint8_t ret = 0xff;
+
+ if (func == 0x00)
+ ret = sis_5600_host_to_pci_read(addr, dev->h2p);
+ else if (func == 0x01)
+ ret = sis_5513_ide_read(addr, dev->ide);
+
+ sis_5600_log("SiS 5600: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5595_write(int func, int addr, uint8_t val, void *priv)
+{
+ const sis_5600_t *dev = (sis_5600_t *) priv;
+
+ sis_5600_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (func) {
+ case 0x00:
+ sis_5513_pci_to_isa_write(addr, val, dev->p2i);
+ break;
+ case 0x01:
+ sis_5595_pmu_write(addr, val, dev->pmu);
+ break;
+ case 0x02:
+ sis_5572_usb_write(addr, val, dev->usb);
+ break;
+ }
+}
+
+static uint8_t
+sis_5595_read(int func, int addr, void *priv)
+{
+ const sis_5600_t *dev = (sis_5600_t *) priv;
+ uint8_t ret = 0xff;
+
+ switch (func) {
+ case 0x00:
+ ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
+ break;
+ case 0x01:
+ ret = sis_5595_pmu_read(addr, dev->pmu);
+ break;
+ case 0x02:
+ ret = sis_5572_usb_read(addr, dev->usb);
+ break;
+ }
+
+ sis_5600_log("SiS 5602: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5600_close(void *priv)
+{
+ sis_5600_t *dev = (sis_5600_t *) priv;
+
+ free(dev);
+}
+
+static void *
+sis_5600_init(UNUSED(const device_t *info))
+{
+ sis_5600_t *dev = (sis_5600_t *) calloc(1, sizeof(sis_5600_t));
+
+ /* Device 0: SiS 5600 */
+ pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5600_read, sis_5600_write, dev, &dev->nb_slot);
+ /* Device 1: SiS 5595 */
+ pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot);
+
+ dev->sis = device_add(&sis_55xx_common_device);
+
+ dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis);
+ if (info->local)
+ dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis);
+ else
+ dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis);
+ dev->h2p = device_add_linked(&sis_5600_h2p_device, dev->sis);
+ dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis);
+ if (info->local)
+ dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis);
+ else
+ dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
+
+ return dev;
+}
+
+const device_t sis_5600_1997_device = {
+ .name = "SiS (5)600 (1997)",
+ .internal_name = "sis_5600_1997",
+ .flags = DEVICE_PCI,
+ .local = 1,
+ .init = sis_5600_init,
+ .close = sis_5600_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_5600_device = {
+ .name = "SiS (5)600",
+ .internal_name = "sis_5600",
+ .flags = DEVICE_PCI,
+ .local = 0,
+ .init = sis_5600_init,
+ .close = sis_5600_close,
+ .reset = NULL,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_5600_h2p.c b/src/chipset/sis_5600_h2p.c
new file mode 100644
index 0000000000..f6ee926da4
--- /dev/null
+++ b/src/chipset/sis_5600_h2p.c
@@ -0,0 +1,434 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the SiS (5)600 Host to PCI bridge.
+ *
+ * Authors: Miran Grca,
+ *
+ * Copyright 2024 Miran Grca.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include <86box/device.h>
+#include <86box/io.h>
+#include <86box/timer.h>
+#include <86box/dma.h>
+#include <86box/mem.h>
+#include <86box/nvr.h>
+#include <86box/hdd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/hdc_ide_sff8038i.h>
+#include <86box/pci.h>
+#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
+#include <86box/plat.h>
+#include <86box/plat_unused.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+#include <86box/spd.h>
+#include <86box/apm.h>
+#include <86box/ddma.h>
+#include <86box/acpi.h>
+#include <86box/smbus.h>
+#include <86box/sis_55xx.h>
+#include <86box/chipset.h>
+#include <86box/usb.h>
+#include <86box/agpgart.h>
+
+#ifdef ENABLE_SIS_5600_HOST_TO_PCI_LOG
+int sis_5600_host_to_pci_do_log = ENABLE_SIS_5600_HOST_TO_PCI_LOG;
+
+static void
+sis_5600_host_to_pci_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (sis_5600_host_to_pci_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define sis_5600_host_to_pci_log(fmt, ...)
+#endif
+
+typedef struct {
+ uint8_t installed;
+ uint8_t code;
+ uint32_t phys_size;
+} ram_bank_t;
+
+typedef struct sis_5600_host_to_pci_t {
+ uint8_t pci_conf[256];
+ uint8_t states[7];
+
+ ram_bank_t ram_banks[3];
+
+ sis_55xx_common_t *sis;
+
+ smram_t *smram;
+
+ agpgart_t *agpgart;
+} sis_5600_host_to_pci_t;
+
+static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b };
+
+static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */
+ 0x01000000, /* 16 MB */
+ 0x02000000, /* 32 MB */
+ 0x04000000, /* 64 MB */
+ 0x08000000, /* 128 MB */
+ 0x10000000, /* 256 MB */
+ 0x20000000 }; /* 512 MB */
+
+static void
+sis_5600_shadow_recalc(sis_5600_host_to_pci_t *dev)
+{
+ int state;
+ uint32_t base;
+
+ for (uint8_t i = 0; i < 8; i++) {
+ base = 0x000c0000 + (i << 14);
+ state = (dev->pci_conf[0x70] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[0x72] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ if (((dev->pci_conf[0x70] ^ dev->states[0]) & (1 << i)) ||
+ ((dev->pci_conf[0x72] ^ dev->states[2]) & (1 << i))) {
+ mem_set_mem_state_both(base, 0x4000, state);
+ sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+ }
+ }
+
+ for (uint8_t i = 0; i < 4; i++) {
+ base = 0x000e0000 + (i << 14);
+ state = (dev->pci_conf[0x71] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[0x73] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << i)) ||
+ ((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << i))) {
+ mem_set_mem_state_both(base, 0x4000, state);
+ sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
+ }
+ }
+
+ base = 0x000f0000;
+ state = (dev->pci_conf[0x71] & (1 << 4)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
+ state |= (dev->pci_conf[0x73] & (1 << 4)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
+ if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << 4)) ||
+ ((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << 4))) {
+ mem_set_mem_state_both(base, 0x10000, state);
+ sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0xffff);
+ }
+
+ for (uint8_t i = 0; i < 4; i++)
+ dev->states[i] = dev->pci_conf[0x70 + i];
+
+ flushmmucache_nopc();
+}
+
+static void
+sis_5600_smram_recalc(sis_5600_host_to_pci_t *dev)
+{
+ smram_disable_all();
+
+ switch (dev->pci_conf[0x6a] >> 6) {
+ case 0:
+ smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1);
+ break;
+ case 1:
+ smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1);
+ break;
+ case 2:
+ smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1);
+ break;
+ case 3:
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x6a] & 0x10, 1);
+ break;
+
+ default:
+ break;
+ }
+
+ flushmmucache();
+}
+
+static void
+sis_5600_mask_bar(uint8_t *regs, void *agpgart)
+{
+ uint32_t bar;
+ uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x00000000 } ;
+
+ /* Make sure the aperture's base is aligned to its size. */
+ bar = (regs[0x13] << 24) | (regs[0x12] << 16);
+ bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000);
+ regs[0x12] = (bar >> 16) & 0xff;
+ regs[0x13] = (bar >> 24) & 0xff;
+
+ if (!agpgart)
+ return;
+
+ /* Map aperture and GART. */
+ agpgart_set_aperture(agpgart,
+ bar,
+ sizes[(regs[0x94] >> 4) & 0x07],
+ !!(regs[0x94] & 0x02));
+ if (regs[0x94] & 0x01)
+ agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24));
+ else
+ agpgart_set_gart(agpgart, 0x00000000);
+}
+
+void
+sis_5600_host_to_pci_write(int addr, uint8_t val, void *priv)
+{
+ sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
+
+ sis_5600_host_to_pci_log("SiS 5600 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
+
+ switch (addr) {
+ default:
+ break;
+
+ case 0x04: /* Command - Low Byte */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
+ break;
+ case 0x05: /* Command - High Byte */
+ dev->pci_conf[addr] = val & 0x03;
+ break;
+
+ case 0x07: /* Status - High Byte */
+ dev->pci_conf[addr] = (dev->pci_conf[addr] & ~(val & 0x70)) | (val & 0x01);
+ break;
+
+ case 0x0d: /* Master latency timer */
+ case 0x50 ... 0x5a:
+ case 0x64 ... 0x69:
+ case 0x6b ... 0x6c:
+ case 0x74 ... 0x75:
+ case 0x77 ... 0x80:
+ case 0x82 ... 0x8f:
+ case 0x97 ... 0x9b:
+ case 0xc8 ... 0xcb:
+ case 0xd4 ... 0xd8:
+ case 0xda:
+ case 0xe0:
+ case 0xe2 ... 0xe3:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x12:
+ dev->pci_conf[addr] = val & 0xc0;
+ sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+ case 0x13:
+ dev->pci_conf[addr] = val;
+ sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+
+ case 0x60 ... 0x62:
+ dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0;
+ break;
+
+ case 0x63:
+ dev->pci_conf[addr] = dev->ram_banks[0].installed |
+ (dev->ram_banks[1].installed << 1) |
+ (dev->ram_banks[2].installed << 2);
+ break;
+
+ case 0x6a:
+ dev->pci_conf[addr] = val;
+ sis_5600_smram_recalc(dev);
+ break;
+
+ case 0x70 ... 0x73:
+ dev->pci_conf[addr] = val;
+ sis_5600_shadow_recalc(dev);
+ break;
+
+ case 0x91 ... 0x93:
+ dev->pci_conf[addr] = val;
+ sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+ case 0x94:
+ dev->pci_conf[addr] = val & 0x7f;
+ sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
+ break;
+ }
+}
+
+uint8_t
+sis_5600_host_to_pci_read(int addr, void *priv)
+{
+ const sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
+ uint8_t ret = 0xff;
+
+ ret = dev->pci_conf[addr];
+
+ sis_5600_host_to_pci_log("SiS 5600 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
+
+ return ret;
+}
+
+static void
+sis_5600_host_to_pci_reset(void *priv)
+{
+ sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
+
+ dev->pci_conf[0x00] = 0x39;
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x00;
+ dev->pci_conf[0x03] = 0x56;
+ dev->pci_conf[0x04] = 0x05;
+ dev->pci_conf[0x05] = 0x00;
+ dev->pci_conf[0x06] = 0x10;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x10;
+ dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x0c] = 0x00;
+ dev->pci_conf[0x0d] = 0xff;
+ dev->pci_conf[0x0e] = 0x80;
+ dev->pci_conf[0x0f] = 0x00;
+ dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00;
+ dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00;
+ dev->pci_conf[0x34] = 0xc0;
+ dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x02;
+ dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00;
+ dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00;
+ dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00;
+ dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00;
+ dev->pci_conf[0x5a] = 0x00;
+ dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
+ dev->pci_conf[0x62] = 0x00;
+ dev->pci_conf[0x63] = 0xff;
+ dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
+ dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
+ dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
+ dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00;
+ dev->pci_conf[0x6c] = 0x00;
+ dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
+ dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
+ dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
+ dev->pci_conf[0x77] = 0x00;
+ dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
+ dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
+ dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00;
+ dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00;
+ dev->pci_conf[0x80] = 0x00;
+ dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
+ dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff;
+ dev->pci_conf[0x86] = 0xff;
+ dev->pci_conf[0x87] = 0x00;
+ dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00;
+ dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00;
+ dev->pci_conf[0x8c] = 0x00;
+ dev->pci_conf[0x8d] = 0x62;
+ dev->pci_conf[0x8e] = dev->pci_conf[0x8f] = 0x00;
+ dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
+ dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00;
+ dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00;
+ dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00;
+ dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00;
+ dev->pci_conf[0xc0] = 0x02;
+ dev->pci_conf[0xc1] = 0x00;
+ dev->pci_conf[0xc2] = 0x10;
+ dev->pci_conf[0xc3] = 0x00;
+ dev->pci_conf[0xc4] = 0x03;
+ dev->pci_conf[0xc5] = 0x02;
+ dev->pci_conf[0xc6] = 0x00;
+ dev->pci_conf[0xc7] = 0x1f;
+ dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00;
+ dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00;
+ dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00;
+ dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00;
+ dev->pci_conf[0xd8] = dev->pci_conf[0xda] = 0x00;
+ dev->pci_conf[0xe0] = 0x00;
+ dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00;
+
+ sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
+
+ cpu_cache_ext_enabled = 1;
+ cpu_update_waitstates();
+
+ sis_5600_shadow_recalc(dev);
+
+ sis_5600_smram_recalc(dev);
+}
+
+static void
+sis_5600_host_to_pci_close(void *priv)
+{
+ sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+static void *
+sis_5600_host_to_pci_init(UNUSED(const device_t *info))
+{
+ sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) calloc(1, sizeof(sis_5600_host_to_pci_t));
+ uint32_t total_mem = mem_size << 10;
+ ram_bank_t *rb;
+
+ dev->sis = device_get_common_priv();
+
+ /* Calculate the physical RAM banks. */
+ for (uint8_t i = 0; i < 3; i++) {
+ rb = &(dev->ram_banks[i]);
+ uint32_t size = 0x00000000;
+ uint8_t index = 0;
+ for (int8_t j = 6; j >= 0; j--) {
+ uint32_t *bs = &(bank_sizes[j]);
+ if (*bs <= total_mem) {
+ size = *bs;
+ index = j;
+ break;
+ }
+ }
+ if (size != 0x00000000) {
+ rb->installed = 1;
+ rb->code = bank_codes[index];
+ rb->phys_size = size;
+ total_mem -= size;
+ } else
+ rb->installed = 0;
+ }
+
+ /* SMRAM */
+ dev->smram = smram_add();
+
+ device_add(&sis_5xxx_agp_device);
+ dev->agpgart = device_add(&agpgart_device);
+
+ sis_5600_host_to_pci_reset(dev);
+
+ return dev;
+}
+
+const device_t sis_5600_h2p_device = {
+ .name = "SiS (5)600 Host to PCI bridge",
+ .internal_name = "sis_5600_host_to_pci",
+ .flags = DEVICE_PCI,
+ .local = 0x00,
+ .init = sis_5600_host_to_pci_init,
+ .close = sis_5600_host_to_pci_close,
+ .reset = sis_5600_host_to_pci_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c
index 4d1db2d9eb..3c3d5bd8cd 100644
--- a/src/chipset/sis_85c496.c
+++ b/src/chipset/sis_85c496.c
@@ -123,7 +123,7 @@ sis_85c497_isa_read(uint16_t port, void *priv)
const sis_85c496_t *dev = (sis_85c496_t *) priv;
uint8_t ret = 0xff;
- if (port == 0x23)
+ if ((port == 0x23) && (dev->cur_reg < 0xc0))
ret = dev->regs[dev->cur_reg];
else if (port == 0x33)
ret = 0x3c /*random_generate()*/;
@@ -388,8 +388,7 @@ sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
break;
case 0x67: /* Miscellaneous Control */
dev->pci_conf[addr] = val & 0xf9;
- if (valxor & 0x60)
- port_92_set_features(dev->port_92, !!(val & 0x20), !!(val & 0x40));
+ cpu_cpurst_on_sr = ((val & 0xa0) == 0x80) && !(dev->pci_conf[0xc6] & 0x08);
break;
/* 86C497 Specific Registers (80h ~ FFh) */
@@ -480,6 +479,8 @@ sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
break;
case 0xc6: /* 85C497 Post / INIT Configuration */
dev->pci_conf[addr] = val & 0x0f;
+ cpu_cpurst_on_sr = ((dev->pci_conf[0x67] & 0xa0) == 0x80) && !(val & 0x08);
+ soft_reset_pci = !!(val & 0x04);
break;
case 0xc8:
case 0xc9:
@@ -608,12 +609,18 @@ sis_85c496_reset(void *priv)
sis_85c49x_pci_write(0, 0xd0, 0x78, dev);
sis_85c49x_pci_write(0, 0xd4, 0x00, dev);
+ dev->pci_conf[0x67] = 0x00;
+ dev->pci_conf[0xc6] = 0x00;
+
ide_pri_disable();
ide_sec_disable();
nvr_bank_set(0, 0, dev->nvr);
sis_85c497_isa_reset(dev);
+
+ cpu_cpurst_on_sr = 0;
+ soft_reset_pci = 0;
}
static void
diff --git a/src/chipset/sis_85c4xx.c b/src/chipset/sis_85c4xx.c
index cf4ff42d7f..f80ecf99e8 100644
--- a/src/chipset/sis_85c4xx.c
+++ b/src/chipset/sis_85c4xx.c
@@ -174,9 +174,7 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
case 0x23:
if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) {
valxor = val ^ dev->regs[rel_reg];
- if (rel_reg == 0x19)
- dev->regs[rel_reg] &= ~val;
- else if (rel_reg == 0x00)
+ if (rel_reg == 0x00)
dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0);
else
dev->regs[rel_reg] = val;
diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c
index 7f4aebb7cb..137ddb5cf2 100644
--- a/src/chipset/sis_85c50x.c
+++ b/src/chipset/sis_85c50x.c
@@ -6,15 +6,13 @@
*
* This file is part of the 86Box distribution.
*
- * Implementation of the SiS 85C50x Chipset.
+ * Implementation of the SiS 85C50x and 550x Chipsets.
*
+ * Authors: Miran Grca,
+ * Tiseno100,
*
- *
- * Authors: Tiseno100,
- * Miran Grca,
- *
- * Copyright 2020-2021 Tiseno100.
- * Copyright 2020-2021 Miran Grca.
+ * Copyright 2020-2024 Miran Grca.
+ * Copyright 2020-2024 Tiseno100.
*/
#include
#include
@@ -27,16 +25,21 @@
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
-
#include <86box/apm.h>
#include <86box/machine.h>
#include <86box/pic.h>
+#include <86box/pit.h>
+#include <86box/pit_fast.h>
#include <86box/plat_unused.h>
#include <86box/mem.h>
+#include <86box/nvr.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/port_92.h>
-
+#include <86box/spd.h>
+#include <86box/hdc.h>
+#include <86box/hdc_ide.h>
+#include <86box/keyboard.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_85C50X_LOG
@@ -58,17 +61,23 @@ sis_85c50x_log(const char *fmt, ...)
#endif
typedef struct sis_85c50x_t {
- uint8_t index;
- uint8_t nb_slot;
- uint8_t sb_slot;
- uint8_t pad;
+ uint8_t index;
+ uint8_t nb_slot;
+ uint8_t sb_slot;
+ uint8_t type;
- uint8_t pci_conf[256];
- uint8_t pci_conf_sb[256];
- uint8_t regs[256];
+ uint8_t pci_conf[256];
+ uint8_t pci_conf_sb[256];
+ uint8_t pci_conf_ide[256];
+ uint8_t regs[256];
+ uint32_t states[13];
smram_t *smram[2];
port_92_t *port_92;
+ void *pit;
+ nvr_t *nvr;
+
+ uint8_t (*pit_read_reg)(void *priv, uint8_t reg);
} sis_85c50x_t;
static void
@@ -77,23 +86,59 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev)
uint32_t base;
uint32_t can_read;
uint32_t can_write;
+ uint32_t state;
can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
can_write = (dev->pci_conf[0x53] & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL;
- if (!can_read)
- can_write = MEM_WRITE_EXTANY;
- mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write);
- shadowbios = 1;
- shadowbios_write = 1;
+ state = can_read | can_write;
+ if (dev->states[12] != state) {
+ mem_set_mem_state_both(0x000f0000, 0x00010000, state);
+ sis_85c50x_log("F0000-FFFFF: R%c, W%c\n",
+ (dev->pci_conf[0x53] & 0x40) ? 'I' : 'E',
+ (dev->pci_conf[0x53] & 0x20) ? 'P' : 'I');
+ dev->states[12] = state;
+ }
for (uint8_t i = 0; i < 4; i++) {
- base = 0xe0000 + (i << 14);
- mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
- base = 0xd0000 + (i << 14);
- mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
- base = 0xc0000 + (i << 14);
- mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
+ base = 0x000e0000 + (i << 14);
+ state = (dev->pci_conf[0x54] & (0x80 >> i)) ?
+ (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ if (dev->states[8 + i] != state) {
+ mem_set_mem_state_both(base, 0x00004000, state);
+ sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff,
+ (dev->pci_conf[0x543 & (0x80 >> i)) ?
+ ((dev->pci_conf[0x54] & 0x40) ? 'I' : 'D') : 'E',
+ (dev->pci_conf[0x54] & (0x80 >> i)) ?
+ ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E');
+ dev->states[8 + i] = state;
+ }
+
+ base = 0x000d0000 + (i << 14);
+ state = (dev->pci_conf[0x55] & (0x80 >> i)) ?
+ (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ if (dev->states[4 + i] != state) {
+ mem_set_mem_state_both(base, 0x00004000, state);
+ sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff,
+ (dev->pci_conf[0x55] & (0x80 >> i)) ?
+ ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E',
+ (dev->pci_conf[0x55] & (0x80 >> i)) ?
+ ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E');
+ dev->states[4 + i] = state;
+ }
+
+ base = 0x000c0000 + (i << 14);
+ state = (dev->pci_conf[0x56] & (0x80 >> i)) ?
+ (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ if (dev->states[i] != state) {
+ mem_set_mem_state_both(base, 0x00004000, state);
+ sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff,
+ (dev->pci_conf[0x56] & (0x80 >> i)) ?
+ ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E',
+ (dev->pci_conf[0x56] & (0x80 >> i)) ?
+ ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E');
+ dev->states[i] = state;
+ }
}
flushmmucache_nopc();
@@ -117,27 +162,35 @@ sis_85c50x_smm_recalc(sis_85c50x_t *dev)
break;
case 0x01:
host_base |= 0x000b0000;
- sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x10000 - 1);
+ sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n",
+ host_base, host_base + 0x10000 - 1);
smram_enable(dev->smram[0], host_base, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
- smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
+ smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000,
+ 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x02:
host_base |= 0x000a0000;
- sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x10000 - 1);
+ sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n",
+ host_base, host_base + 0x10000 - 1);
smram_enable(dev->smram[0], host_base, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
- smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
+ smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000,
+ 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x04:
host_base |= 0x000a0000;
- sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x8000 - 1);
+ sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n",
+ host_base, host_base + 0x8000 - 1);
smram_enable(dev->smram[0], host_base, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
- smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
+ smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000,
+ 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x06:
host_base |= 0x000b0000;
- sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x8000 - 1);
+ sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n",
+ host_base, host_base + 0x8000 - 1);
smram_enable(dev->smram[0], host_base, 0xb0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
- smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
+ smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000,
+ 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
default:
break;
@@ -160,7 +213,10 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06);
break;
case 0x50:
- dev->pci_conf[addr] = val;
+ if (dev->type & 1)
+ dev->pci_conf[addr] = val & 0xf7;
+ else
+ dev->pci_conf[addr] = val;
break;
case 0x51: /* Cache */
dev->pci_conf[addr] = val;
@@ -176,8 +232,6 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
case 0x56:
dev->pci_conf[addr] = val;
sis_85c50x_shadow_recalc(dev);
- if (addr == 0x54)
- sis_85c50x_smm_recalc(dev);
break;
case 0x57:
case 0x58:
@@ -204,6 +258,7 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x5b:
dev->pci_conf[addr] = val;
+ kbc_at_set_fast_reset(!!(val & 0x40));
break;
case 0x60: /* SMI */
if ((dev->pci_conf[0x68] & 0x01) && !(dev->pci_conf[addr] & 0x02) && (val & 0x02)) {
@@ -223,6 +278,31 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
case 0x69:
dev->pci_conf[addr] &= ~val;
break;
+ case 0x70 ... 0x77:
+ if (dev->type & 1)
+ spd_write_drbs(dev->pci_conf, 0x70, 0x77, 2);
+ break;
+ case 0x78:
+ case 0x7c ... 0x7e:
+ if (dev->type & 1)
+ dev->pci_conf[addr] = val;
+ break;
+ case 0x79:
+ if (dev->type & 1) {
+ spd_write_drbs(dev->pci_conf, 0xf8, 0xff, 4);
+ dev->pci_conf[addr] = 0x00;
+ for (uint8_t i = 0; i < 8; i++)
+ if (dev->pci_conf[0xf8 + i] & 0x80) dev->pci_conf[addr] |= (1 << i);
+ }
+ break;
+ case 0x7a:
+ if (dev->type & 1)
+ dev->pci_conf[addr] = val & 0xfe;
+ break;
+ case 0x7b:
+ if (dev->type & 1)
+ dev->pci_conf[addr] = val & 0xe0;
+ break;
default:
break;
@@ -235,14 +315,33 @@ sis_85c50x_read(int func, int addr, void *priv)
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
- if (func == 0x00)
- ret = dev->pci_conf[addr];
+ if (func == 0x00) {
+ if (addr >= 0xf8)
+ ret = 0x00;
+ else
+ ret = dev->pci_conf[addr];
+ }
sis_85c50x_log("85C501: [R] (%02X, %02X) = %02X\n", func, addr, ret);
return ret;
}
+static void
+sis_85c50x_ide_recalc(sis_85c50x_t *dev)
+{
+ ide_pri_disable();
+ ide_set_base(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0170 : 0x01f0);
+ ide_set_side(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0376 : 0x03f6);
+ ide_pri_enable();
+
+ ide_sec_disable();
+ ide_set_base(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x01f0 : 0x0170);
+ ide_set_side(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x03f6 : 0x0376);
+ if (dev->pci_conf_ide[0x41] & 0x01)
+ ide_sec_enable();
+}
+
static void
sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
{
@@ -250,38 +349,46 @@ sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, val);
- if (func == 0x00)
- switch (addr) {
- case 0x04: /* Command */
- dev->pci_conf_sb[addr] = val & 0x0f;
- break;
- case 0x07: /* Status */
- dev->pci_conf_sb[addr] &= ~(val & 0x30);
- break;
- case 0x40: /* BIOS Control Register */
- dev->pci_conf_sb[addr] = val & 0x3f;
- break;
- case 0x41:
- case 0x42:
- case 0x43:
- case 0x44:
- /* INTA/B/C/D# Remapping Control Register */
- dev->pci_conf_sb[addr] = val & 0x8f;
- if (val & 0x80)
- pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED);
- else
- pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf);
- break;
- case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
- case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
- case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
- case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
- dev->pci_conf_sb[addr] = val;
- break;
+ if (func == 0x00) switch (addr) {
+ case 0x04: /* Command */
+ dev->pci_conf_sb[addr] = val & 0x0f;
+ break;
+ case 0x07: /* Status */
+ dev->pci_conf_sb[addr] &= ~(val & 0x30);
+ break;
+ case 0x40: /* BIOS Control Register */
+ dev->pci_conf_sb[addr] = val & 0x3f;
+ break;
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ /* INTA/B/C/D# Remapping Control Register */
+ dev->pci_conf_sb[addr] = val & 0x8f;
+ if (val & 0x80)
+ pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED);
+ else
+ pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf);
+ break;
+ case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
+ case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
+ case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
+ case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
+ dev->pci_conf_sb[addr] = val;
+ break;
- default:
- break;
- }
+ default:
+ break;
+ } else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01)) switch (addr) {
+ case 0x40:
+ case 0x41:
+ dev->pci_conf_ide[addr] = val;
+ sis_85c50x_ide_recalc(dev);
+ break;
+
+ default:
+ break;
+ }
}
static uint8_t
@@ -290,8 +397,42 @@ sis_85c50x_sb_read(int func, int addr, void *priv)
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
- if (func == 0x00)
- ret = dev->pci_conf_sb[addr];
+ if (func == 0x00) switch (addr) {
+ default:
+ ret = dev->pci_conf_sb[addr];
+ break;
+ case 0x4c ... 0x4f:
+ if (dev->type & 2)
+ ret = pic_read_icw(0, addr & 0x03);
+ else
+ ret = dev->pci_conf_sb[addr];
+ break;
+ case 0x50 ... 0x53:
+ if (dev->type & 2)
+ ret = pic_read_icw(1, addr & 0x03);
+ else
+ ret = dev->pci_conf_sb[addr];
+ break;
+ case 0x54 ... 0x55:
+ if (dev->type & 2)
+ ret = pic_read_ocw(0, addr & 0x01);
+ else
+ ret = dev->pci_conf_sb[addr];
+ break;
+ case 0x56 ... 0x57:
+ if (dev->type & 2)
+ ret = pic_read_ocw(1, addr & 0x01);
+ else
+ ret = dev->pci_conf_sb[addr];
+ break;
+ case 0x58 ... 0x5f:
+ if (dev->type & 2)
+ ret = dev->pit_read_reg(dev->pit, addr & 0x07);
+ else
+ ret = dev->pci_conf_sb[addr];
+ break;
+ } else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01))
+ ret = dev->pci_conf_ide[addr];
sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, ret);
@@ -313,10 +454,39 @@ sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv)
case 0x23:
switch (dev->index) {
case 0x80:
- dev->regs[dev->index] = val & 0xe7;
+ if (dev->type & 2) {
+ dev->regs[dev->index] = val;
+ nvr_bank_set(0, !!(val & 0x08), dev->nvr);
+ } else
+ dev->regs[dev->index] = val & 0xe7;
+ switch (val >> 6) {
+ case 0:
+ cpu_set_isa_speed(7159091);
+ break;
+ case 1:
+ cpu_set_isa_pci_div(4);
+ break;
+ case 2:
+ cpu_set_isa_pci_div(3);
+ break;
+
+ default:
+ break;
+ }
break;
case 0x81:
- dev->regs[dev->index] = val & 0xf4;
+ if (dev->type & 2)
+ dev->regs[dev->index] = val & 0xf6;
+ else
+ dev->regs[dev->index] = val & 0xf4;
+ break;
+ case 0x82:
+ if (dev->type & 2)
+ dev->regs[dev->index] = val;
+ break;
+ case 0x83:
+ if (dev->type & 2)
+ dev->regs[dev->index] = val & 0x03;
break;
case 0x84:
case 0x88:
@@ -394,6 +564,12 @@ sis_85c50x_reset(void *priv)
sis_85c50x_write(0, 0x68, 0x00, dev);
sis_85c50x_write(0, 0x69, 0xff, dev);
+ if (dev->type & 1) {
+ for (uint8_t i = 0; i < 8; i++)
+ dev->pci_conf[0x70 + i] = 0x00;
+ dev->pci_conf[0x79] = 0x00;
+ }
+
/* South Bridge (SiS 85C503) */
dev->pci_conf_sb[0x00] = 0x39;
dev->pci_conf_sb[0x01] = 0x10;
@@ -407,10 +583,51 @@ sis_85c50x_reset(void *priv)
dev->pci_conf_sb[0x09] = 0x00;
dev->pci_conf_sb[0x0a] = 0x01;
dev->pci_conf_sb[0x0b] = 0x06;
+ if (dev->type & 2)
+ dev->pci_conf_sb[0x0e] = 0x80;
sis_85c50x_sb_write(0, 0x41, 0x80, dev);
sis_85c50x_sb_write(0, 0x42, 0x80, dev);
sis_85c50x_sb_write(0, 0x43, 0x80, dev);
sis_85c50x_sb_write(0, 0x44, 0x80, dev);
+
+ if (dev->type & 2) {
+ /* IDE (SiS 5503) */
+ dev->pci_conf_ide[0x00] = 0x39;
+ dev->pci_conf_ide[0x01] = 0x10;
+ dev->pci_conf_ide[0x02] = 0x01;
+ dev->pci_conf_ide[0x03] = 0x06;
+ dev->pci_conf_ide[0x04] = 0x89;
+ dev->pci_conf_ide[0x05] = 0x00;
+ dev->pci_conf_ide[0x06] = 0x00;
+ dev->pci_conf_ide[0x07] = 0x00;
+ dev->pci_conf_ide[0x08] = 0x00;
+ dev->pci_conf_ide[0x09] = 0x00;
+ dev->pci_conf_ide[0x0a] = 0x01;
+ dev->pci_conf_ide[0x0b] = 0x01;
+ dev->pci_conf_ide[0x0c] = 0x00;
+ dev->pci_conf_ide[0x0d] = 0x00;
+ dev->pci_conf_ide[0x0e] = 0x80;
+ dev->pci_conf_ide[0x0f] = 0x00;
+ dev->pci_conf_ide[0x10] = 0x71;
+ dev->pci_conf_ide[0x11] = 0x01;
+ dev->pci_conf_ide[0x14] = 0xf1;
+ dev->pci_conf_ide[0x15] = 0x01;
+ dev->pci_conf_ide[0x18] = 0x71;
+ dev->pci_conf_ide[0x19] = 0x03;
+ dev->pci_conf_ide[0x1c] = 0xf1;
+ dev->pci_conf_ide[0x1d] = 0x03;
+ dev->pci_conf_ide[0x20] = 0x01;
+ dev->pci_conf_ide[0x24] = 0x01;
+ dev->pci_conf_ide[0x40] = 0x00;
+ dev->pci_conf_ide[0x41] = 0x40;
+
+ sis_85c50x_ide_recalc(dev);
+ }
+
+ cpu_set_isa_speed(7159091);
+
+ if (dev->type & 2)
+ nvr_bank_set(0, 0, dev->nvr);
}
static void
@@ -426,8 +643,10 @@ sis_85c50x_close(void *priv)
static void *
sis_85c50x_init(UNUSED(const device_t *info))
{
- sis_85c50x_t *dev = (sis_85c50x_t *) malloc(sizeof(sis_85c50x_t));
- memset(dev, 0x00, sizeof(sis_85c50x_t));
+ sis_85c50x_t *dev = (sis_85c50x_t *) calloc(1, sizeof(sis_85c50x_t));
+ uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
+
+ dev->type = info->local;
/* 501/502 (Northbridge) */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot);
@@ -441,6 +660,17 @@ sis_85c50x_init(UNUSED(const device_t *info))
dev->port_92 = device_add(&port_92_device);
+ if (dev->type & 2) {
+ /* PIT */
+ dev->pit = device_find_first_priv(DEVICE_PIT);
+ dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg;
+
+ /* NVR */
+ dev->nvr = device_add(&at_mb_nvr_device);
+
+ device_add(&ide_pci_2ch_device);
+ }
+
sis_85c50x_reset(dev);
return dev;
@@ -459,3 +689,45 @@ const device_t sis_85c50x_device = {
.force_redraw = NULL,
.config = NULL
};
+
+const device_t sis_550x_85c503_device = {
+ .name = "SiS 550x",
+ .internal_name = "sis_550x",
+ .flags = DEVICE_PCI,
+ .local = 1,
+ .init = sis_85c50x_init,
+ .close = sis_85c50x_close,
+ .reset = sis_85c50x_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_85c50x_5503_device = {
+ .name = "SiS 85C50x",
+ .internal_name = "sis_85c50x",
+ .flags = DEVICE_PCI,
+ .local = 2,
+ .init = sis_85c50x_init,
+ .close = sis_85c50x_close,
+ .reset = sis_85c50x_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t sis_550x_device = {
+ .name = "SiS 550x",
+ .internal_name = "sis_550x",
+ .flags = DEVICE_PCI,
+ .local = 3,
+ .init = sis_85c50x_init,
+ .close = sis_85c50x_close,
+ .reset = sis_85c50x_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c
index f6a9233469..7a049b1cbe 100644
--- a/src/chipset/umc_8886.c
+++ b/src/chipset/umc_8886.c
@@ -79,17 +79,14 @@
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
-
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/pic.h>
#include <86box/pci.h>
-
+#include <86box/port_92.h>
#include <86box/chipset.h>
-#define IDE_BIT 0x01
-
#ifdef ENABLE_UMC_8886_LOG
int umc_8886_do_log = ENABLE_UMC_8886_LOG;
@@ -108,18 +105,6 @@ umc_8886_log(const char *fmt, ...)
# define umc_8886_log(fmt, ...)
#endif
-/* PCI IRQ Flags */
-#define INTA (PCI_INTA + (2 * !(addr & 1)))
-#define INTB (PCI_INTB + (2 * !(addr & 1)))
-#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED)
-#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED)
-
-/* Disable Internal IDE Flag needed for the AF or BF Southbridge variant */
-#define HAS_IDE dev->has_ide
-
-/* Southbridge Revision */
-#define SB_ID dev->sb_id
-
typedef struct umc_8886_t {
uint8_t max_func; /* Last function number */
uint8_t pci_slot;
@@ -128,19 +113,24 @@ typedef struct umc_8886_t {
uint8_t pci_conf_sb[2][256]; /* PCI Registers */
- uint16_t sb_id; /* Southbridge Revision */
- int has_ide; /* Check if Southbridge Revision is AF or F */
+ uint16_t sb_id; /* Southbridge Revision */
+ uint16_t ide_id; /* IDE Revision */
+
+ int has_ide; /* Check if Southbridge Revision is F, AF, or BF */
} umc_8886_t;
static void
-umc_8886_ide_handler(int status)
+umc_8886_ide_handler(umc_8886_t *dev)
{
ide_pri_disable();
ide_sec_disable();
- if (status) {
- ide_pri_enable();
- ide_sec_enable();
+ if (dev->pci_conf_sb[1][0x04] & 0x01) {
+ if (dev->pci_conf_sb[1][0x40] & 0x80)
+ ide_pri_enable();
+
+ if (dev->pci_conf_sb[1][0x40] & 0x40)
+ ide_sec_enable();
}
}
@@ -148,6 +138,7 @@ static void
umc_8886_write(int func, int addr, uint8_t val, void *priv)
{
umc_8886_t *dev = (umc_8886_t *) priv;
+ int irq_routing;
if (func <= dev->max_func)
switch (func) {
@@ -155,8 +146,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80));
switch (addr) {
- case 0x04:
- case 0x05:
+ case 0x04 ... 0x05:
+ case 0x0c ... 0x0d:
+ case 0x40 ... 0x42:
+ case 0x45:
+ case 0x50 ... 0x55:
+ case 0x57:
+ case 0x70 ... 0x76:
+ case 0x80 ... 0x82:
+ case 0x90 ... 0x92:
+ case 0xa0 ... 0xa1:
+ case 0xa5 ... 0xa8:
dev->pci_conf_sb[func][addr] = val;
break;
@@ -164,46 +164,31 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf_sb[func][addr] &= ~(val & 0xf9);
break;
- case 0x0c:
- case 0x0d:
- dev->pci_conf_sb[func][addr] = val;
- break;
-
- case 0x40:
- case 0x41:
- case 0x42:
- dev->pci_conf_sb[func][addr] = val;
- break;
-
case 0x43:
- case 0x44:
dev->pci_conf_sb[func][addr] = val;
- pci_set_irq_routing(INTA, IRQRECALCA);
- pci_set_irq_routing(INTB, IRQRECALCB);
+ irq_routing = (dev->pci_conf_sb[func][0x46] & 0x01) ? (val >> 8) :
+ PCI_IRQ_DISABLED;
+ pci_set_irq_routing(PCI_INTA, irq_routing);
+ irq_routing = (dev->pci_conf_sb[func][0x46] & 0x02) ? (val & 0x0f) :
+ PCI_IRQ_DISABLED;
+ pci_set_irq_routing(PCI_INTB, irq_routing);
break;
-
- case 0x45:
+ case 0x44:
dev->pci_conf_sb[func][addr] = val;
+ irq_routing = (dev->pci_conf_sb[func][0x46] & 0x04) ? (val >> 8) :
+ PCI_IRQ_DISABLED;
+ pci_set_irq_routing(PCI_INTC, irq_routing);
+ irq_routing = (dev->pci_conf_sb[func][0x46] & 0x08) ? (val & 0x0f) :
+ PCI_IRQ_DISABLED;
+ pci_set_irq_routing(PCI_INTD, irq_routing);
break;
- case 0x46:
+ case 0x46: /* Bits 3-0 = 0 = IRQ disabled, 1 = IRQ enabled. */
+ case 0x47: /* Bits 3-0 = 0 = IRQ edge-triggered, 1 = IRQ level-triggered. */
/* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */
dev->pci_conf_sb[func][addr] = val;
break;
- case 0x47:
- dev->pci_conf_sb[func][addr] = val;
- break;
-
- case 0x50:
- case 0x51:
- case 0x52:
- case 0x53:
- case 0x54:
- case 0x55:
- dev->pci_conf_sb[func][addr] = val;
- break;
-
case 0x56:
dev->pci_conf_sb[func][addr] = val;
@@ -220,16 +205,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
default:
break;
}
-
- break;
-
- case 0x57:
- case 0x70 ... 0x76:
- case 0x80:
- case 0x81:
- case 0x90 ... 0x92:
- case 0xa0 ... 0xa1:
- dev->pci_conf_sb[func][addr] = val;
break;
case 0xa2:
@@ -243,7 +218,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10));
else
smi_raise();
- dev->pci_conf_sb[0][0xa3] |= 0x04;
}
dev->pci_conf_sb[func][addr] = val;
@@ -254,10 +228,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2));
break;
- case 0xa5 ... 0xa8:
- dev->pci_conf_sb[func][addr] = val;
- break;
-
default:
break;
}
@@ -269,7 +239,8 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
switch (addr) {
case 0x04:
dev->pci_conf_sb[func][addr] = val;
- umc_8886_ide_handler(val & 1);
+ if (dev->ide_id == 0x673a)
+ umc_8886_ide_handler(dev);
break;
case 0x07:
@@ -277,9 +248,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x3c:
+ case 0x41 ... 0x4b:
+ case 0x54 ... 0x59:
+ if (dev->ide_id == 0x673a)
+ dev->pci_conf_sb[func][addr] = val;
+ break;
+
case 0x40:
- case 0x41:
- dev->pci_conf_sb[func][addr] = val;
+ if (dev->ide_id == 0x673a) {
+ dev->pci_conf_sb[func][addr] = val;
+ umc_8886_ide_handler(dev);
+ }
break;
default:
@@ -311,47 +290,73 @@ umc_8886_reset(void *priv)
memset(dev->pci_conf_sb[0], 0x00, sizeof(dev->pci_conf_sb[0]));
memset(dev->pci_conf_sb[1], 0x00, sizeof(dev->pci_conf_sb[1]));
- dev->pci_conf_sb[0][0] = 0x60; /* UMC */
- dev->pci_conf_sb[0][1] = 0x10;
-
- dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */
- dev->pci_conf_sb[0][3] = ((SB_ID >> 8) & 0xff);
-
- dev->pci_conf_sb[0][4] = 0x0f;
- dev->pci_conf_sb[0][7] = 2;
-
- dev->pci_conf_sb[0][8] = 0x0e;
-
+ dev->pci_conf_sb[0][0x00] = 0x60; /* UMC */
+ dev->pci_conf_sb[0][0x01] = 0x10;
+ dev->pci_conf_sb[0][0x02] = (dev->sb_id & 0xff); /* 8886xx */
+ dev->pci_conf_sb[0][0x03] = ((dev->sb_id >> 8) & 0xff);
+ dev->pci_conf_sb[0][0x04] = 0x0f;
+ dev->pci_conf_sb[0][0x07] = 0x02;
+ dev->pci_conf_sb[0][0x08] = 0x0e;
dev->pci_conf_sb[0][0x09] = 0x00;
dev->pci_conf_sb[0][0x0a] = 0x01;
dev->pci_conf_sb[0][0x0b] = 0x06;
-
- dev->pci_conf_sb[0][0x40] = 1;
- dev->pci_conf_sb[0][0x41] = 6;
- dev->pci_conf_sb[0][0x42] = 8;
- dev->pci_conf_sb[0][0x43] = 0x9a;
- dev->pci_conf_sb[0][0x44] = 0xbc;
- dev->pci_conf_sb[0][0x45] = 4;
+ dev->pci_conf_sb[0][0x40] = 0x01;
+ dev->pci_conf_sb[0][0x41] = 0x06;
+ dev->pci_conf_sb[0][0x42] = 0x08;
+ dev->pci_conf_sb[0][0x43] = 0x00;
+ dev->pci_conf_sb[0][0x44] = 0x00;
+ dev->pci_conf_sb[0][0x45] = 0x04;
+ dev->pci_conf_sb[0][0x46] = 0x00;
dev->pci_conf_sb[0][0x47] = 0x40;
- dev->pci_conf_sb[0][0x50] = 1;
- dev->pci_conf_sb[0][0x51] = 3;
+ dev->pci_conf_sb[0][0x50] = 0x01;
+ dev->pci_conf_sb[0][0x51] = 0x03;
+ dev->pci_conf_sb[0][0x56] = dev->pci_conf_sb[0][0x57] = 0x00;
+ dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00;
+ dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00;
+ dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x76] = 0x00;
+ dev->pci_conf_sb[0][0x82] = 0x00;
+ dev->pci_conf_sb[0][0x90] = dev->pci_conf_sb[0][0x91] = 0x00;
+ dev->pci_conf_sb[0][0xa0] = dev->pci_conf_sb[0][0xa2] = 0x00;
+ dev->pci_conf_sb[0][0xa4] = 0x00;
dev->pci_conf_sb[0][0xa8] = 0x20;
- if (HAS_IDE) {
- dev->pci_conf_sb[1][0] = 0x60; /* UMC */
- dev->pci_conf_sb[1][1] = 0x10;
-
- dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */
- dev->pci_conf_sb[1][3] = 0x67;
-
- dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */
-
- dev->pci_conf_sb[1][8] = 0x10;
-
- dev->pci_conf_sb[1][0x09] = 0x0f;
- dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 1;
-
- umc_8886_ide_handler(1);
+ if (dev->has_ide) {
+ dev->pci_conf_sb[1][0x00] = 0x60; /* UMC */
+ dev->pci_conf_sb[1][0x01] = 0x10;
+ dev->pci_conf_sb[1][0x02] = (dev->ide_id & 0xff); /* 8886xx IDE */
+ dev->pci_conf_sb[1][0x03] = ((dev->ide_id >> 8) & 0xff);
+ dev->pci_conf_sb[1][0x04] = 0x05; /* Start with Internal IDE Enabled */
+ dev->pci_conf_sb[1][0x08] = 0x10;
+ dev->pci_conf_sb[1][0x09] = 0x8f;
+ dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01;
+ dev->pci_conf_sb[1][0x10] = 0xf1;
+ dev->pci_conf_sb[1][0x11] = 0x01;
+ dev->pci_conf_sb[1][0x14] = 0xf5;
+ dev->pci_conf_sb[1][0x15] = 0x03;
+ dev->pci_conf_sb[1][0x18] = 0x71;
+ dev->pci_conf_sb[1][0x19] = 0x01;
+ dev->pci_conf_sb[1][0x1c] = 0x75;
+ dev->pci_conf_sb[1][0x1d] = 0x03;
+ dev->pci_conf_sb[1][0x20] = 0x01;
+ dev->pci_conf_sb[1][0x21] = 0x10;
+
+ if (dev->ide_id == 0x673a) {
+ dev->pci_conf_sb[1][0x40] = 0xc0;
+ dev->pci_conf_sb[1][0x41] = 0x00;
+ dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00;
+ dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00;
+ dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00;
+ dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00;
+ dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x00;
+ dev->pci_conf_sb[1][0x54] = dev->pci_conf_sb[1][0x55] = 0x00;
+ dev->pci_conf_sb[1][0x56] = dev->pci_conf_sb[1][0x57] = 0x00;
+ dev->pci_conf_sb[1][0x58] = dev->pci_conf_sb[1][0x59] = 0x00;
+
+ umc_8886_ide_handler(dev);
+
+ picintc(1 << 14);
+ picintc(1 << 15);
+ }
}
for (uint8_t i = 1; i < 5; i++) /* Disable all IRQ interrupts */
@@ -375,17 +380,28 @@ umc_8886_init(const device_t *info)
umc_8886_t *dev = (umc_8886_t *) malloc(sizeof(umc_8886_t));
memset(dev, 0, sizeof(umc_8886_t));
- dev->has_ide = !!(info->local == 0x886a);
- pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Device 12: UMC 8886xx */
+ /* Device 12: UMC 8886xx */
+ pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot);
- /* Add IDE if UM8886AF variant */
- if (HAS_IDE)
- device_add(&ide_pci_2ch_device);
+ /* Get the Southbridge Revision */
+ dev->sb_id = info->local & 0xffff;
- dev->max_func = (HAS_IDE) ? 1 : 0;
+ /* IDE Revision */
+ dev->ide_id = info->local >> 16;
- /* Get the Southbridge Revision */
- SB_ID = info->local;
+ dev->has_ide = (dev->ide_id != 0x0000);
+
+ dev->max_func = 0;
+
+ /* Add IDE if this is the UM8886AF or UM8886BF. */
+ if (dev->ide_id == 0x673a) {
+ /* UM8886BF */
+ device_add(&ide_pci_2ch_device);
+ dev->max_func = 1;
+ } else if (dev->ide_id == 0x1001) {
+ /* UM8886AF */
+ device_add(&ide_um8673f_device);
+ }
umc_8886_reset(dev);
@@ -396,7 +412,7 @@ const device_t umc_8886f_device = {
.name = "UMC 8886F",
.internal_name = "umc_8886f",
.flags = DEVICE_PCI,
- .local = 0x8886,
+ .local = 0x00008886,
.init = umc_8886_init,
.close = umc_8886_close,
.reset = umc_8886_reset,
@@ -407,10 +423,24 @@ const device_t umc_8886f_device = {
};
const device_t umc_8886af_device = {
- .name = "UMC 8886AF/8886BF",
+ .name = "UMC 8886AF",
.internal_name = "umc_8886af",
.flags = DEVICE_PCI,
- .local = 0x886a,
+ .local = 0x1001886a,
+ .init = umc_8886_init,
+ .close = umc_8886_close,
+ .reset = umc_8886_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
+
+const device_t umc_8886bf_device = {
+ .name = "UMC 8886BF",
+ .internal_name = "umc_8886bf",
+ .flags = DEVICE_PCI,
+ .local = 0x673a888a,
.init = umc_8886_init,
.close = umc_8886_close,
.reset = umc_8886_reset,
diff --git a/src/chipset/umc_8890.c b/src/chipset/umc_8890.c
new file mode 100644
index 0000000000..7de2ca1d08
--- /dev/null
+++ b/src/chipset/umc_8890.c
@@ -0,0 +1,241 @@
+/*
+ * 86Box A hypervisor and IBM PC system emulator that specializes in
+ * running old operating systems and software designed for IBM
+ * PC systems and compatibles from 1981 through fairly recent
+ * system designs based on the PCI bus.
+ *
+ * This file is part of the 86Box distribution.
+ *
+ * Implementation of the UMC 8890 Chipset.
+ *
+ * Note: This chipset has no datasheet, everything were done via
+ * reverse engineering the BIOS of various machines using it.
+ *
+ * Authors: Tiseno100,
+ * Miran Grca,
+ *
+ * Copyright 2021 Tiseno100.
+ * Copyright 2021-2024 Miran Grca.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#define HAVE_STDARG_H
+#include <86box/86box.h>
+#include "cpu.h"
+#include <86box/timer.h>
+#include <86box/io.h>
+#include <86box/device.h>
+
+#include <86box/apm.h>
+#include <86box/mem.h>
+#include <86box/pci.h>
+#include <86box/port_92.h>
+#include <86box/smram.h>
+
+#include <86box/chipset.h>
+
+#ifdef ENABLE_UMC_8890_LOG
+int umc_8890_do_log = ENABLE_UMC_8890_LOG;
+
+static void
+umc_8890_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (umc_8890_do_log) {
+ va_start(ap, fmt);
+ pclog_ex(fmt, ap);
+ va_end(ap);
+ }
+}
+#else
+# define umc_8890_log(fmt, ...)
+#endif
+
+typedef struct umc_8890_t {
+ uint8_t pci_slot;
+
+ uint8_t pci_conf[256]; /* PCI Registers */
+
+ int mem_state[2];
+
+ uint32_t smram_base;
+
+ smram_t *smram; /* SMRAM Handler */
+} umc_8890_t;
+
+static void
+um8890_shadow(umc_8890_t *dev)
+{
+ uint8_t flag;
+ uint16_t state;
+
+ flag = (dev->pci_conf[0x5f] & 0x0c) >> 2;
+ state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) :
+ (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+
+ if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0x0c) {
+ mem_set_mem_state_both(0xe0000, 0x10000, state);
+ dev->mem_state[1] = (dev->mem_state[1] & 0xf0) | (dev->pci_conf[0x5f] & 0x0f);
+ }
+
+ flag = (dev->pci_conf[0x5f] & 0xc0) >> 6;
+ state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) :
+ (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+
+ if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0xc0) {
+ mem_set_mem_state_both(0xf0000, 0x10000, state);
+ dev->mem_state[1] = (dev->mem_state[1] & 0x0f) | (dev->pci_conf[0x5f] & 0xf0);
+ }
+
+ for (uint8_t i = 0; i < 8; i++) {
+ state = (dev->pci_conf[0x5d] & (1 << i)) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) :
+ (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+
+ if ((dev->mem_state[0] ^ dev->pci_conf[0x5d]) & (1 << i)) {
+ mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, state);
+ dev->mem_state[0] = (dev->mem_state[0] & ~(1 << i)) | (dev->pci_conf[0x5d] & (1 << i));
+ }
+ }
+
+ flushmmucache_nopc();
+}
+
+
+static void
+um8890_smram(umc_8890_t *dev)
+{
+ smram_disable_all();
+
+ /* Bit 4, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled
+ in SMM, and is always set to A0000-BFFFF. */
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x65] & 0x10, 1);
+}
+
+static void
+um8890_write(int func, int addr, uint8_t val, void *priv)
+{
+ umc_8890_t *dev = (umc_8890_t *)priv;
+
+ if (func == 0) switch (addr) {
+ case 0x04 ... 0x05:
+ case 0x0c ... 0x0d:
+ case 0x40 ... 0x5b:
+ case 0x60 ... 0x63:
+ case 0x66 ... 0xff:
+ dev->pci_conf[addr] = val;
+ break;
+
+ case 0x07:
+ dev->pci_conf[addr] &= ~(val & 0xf9);
+ break;
+
+ case 0x5c ... 0x5f:
+ dev->pci_conf[addr] = val;
+ um8890_shadow(dev);
+ break;
+
+ /* Register 64h, 16-bit:
+ Bit 12: SMRAM enabled outside SMM (1 = yes, 0 = no);
+ Bit 10: ???? (set by Award BIOS);
+ Bits 7- 0: SMM handler offset to SMBASE, shifted to the right by 14.
+ */
+ case 0x64: case 0x65:
+ dev->pci_conf[addr] = val;
+ if (addr == 0x65)
+ um8890_smram(dev);
+ break;
+ }
+
+ umc_8890_log("UM8890: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80));
+}
+
+
+static uint8_t
+um8890_read(int func, int addr, void *priv)
+{
+ umc_8890_t *dev = (umc_8890_t *)priv;
+ uint8_t ret = 0xff;
+
+ if (func == 0)
+ ret = dev->pci_conf[addr];
+
+ return ret;
+}
+
+static void
+umc_8890_reset(void *priv)
+{
+ umc_8890_t *dev = (umc_8890_t *)priv;
+
+ memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
+
+ /* Defaults */
+ dev->pci_conf[0x00] = 0x60; /* UMC */
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x91; /* 8891F */
+ dev->pci_conf[0x03] = 0x88;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x01;
+ dev->pci_conf[0x09] = 0x00;
+ dev->pci_conf[0x0a] = 0x00;
+ dev->pci_conf[0x0b] = 0x06;
+ dev->pci_conf[0x5c] = 0x00;
+ dev->pci_conf[0x5d] = 0x00;
+ dev->pci_conf[0x5e] = 0x00;
+ dev->pci_conf[0x5f] = 0x00;
+ dev->pci_conf[0x64] = 0x00;
+ dev->pci_conf[0x65] = 0x00;
+
+ um8890_shadow(dev);
+
+ um8890_smram(dev);
+}
+
+
+static void
+umc_8890_close(void *priv)
+{
+ umc_8890_t *dev = (umc_8890_t *)priv;
+
+ smram_del(dev->smram);
+ free(dev);
+}
+
+
+static void *
+umc_8890_init(const device_t *info)
+{
+ umc_8890_t *dev = (umc_8890_t *) calloc(1, sizeof(umc_8890_t));
+
+ /* Device 0: UMC 8890 */
+ pci_add_card(PCI_ADD_NORTHBRIDGE, um8890_read, um8890_write, dev, &dev->pci_slot);
+
+ /* Port 92 */
+ device_add(&port_92_pci_device);
+
+ dev->smram = smram_add();
+
+ umc_8890_reset(dev);
+
+ return dev;
+}
+
+const device_t umc_8890_device = {
+ .name = "UMC 8890(8891BF/8892BF)",
+ .internal_name = "umc_8890",
+ .flags = DEVICE_PCI,
+ .local = 0x886a,
+ .init = umc_8890_init,
+ .close = umc_8890_close,
+ .reset = umc_8890_reset,
+ { .available = NULL },
+ .speed_changed = NULL,
+ .force_redraw = NULL,
+ .config = NULL
+};
diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c
index d5cce0fca3..a7ed0b880e 100644
--- a/src/chipset/umc_hb4.c
+++ b/src/chipset/umc_hb4.c
@@ -14,13 +14,11 @@
* Note 2: Additional information were also used from all
* around the web.
*
- *
- *
* Authors: Tiseno100,
* Miran Grca,
*
* Copyright 2021 Tiseno100.
- * Copyright 2021 Miran Grca.
+ * Copyright 2021-2024 Miran Grca.
*/
/*
@@ -75,15 +73,24 @@
Bit 3: CC000-CFFFF Read Enable
Bit 2: C8000-CBFFF Read Enable
Bit 1: C0000-C7FFF Read Enable
- Bit 0: Enable C0000-DFFFF Shadow Segment Bits
+ Bit 0: E0000-EFFFF Read Enable
Register 55:
- Bit 7: E0000-FFFF Read Enable
+ Bit 7: F0000-FFFF Read Enable
Bit 6: Shadow Write Status (1: Write Protect/0: Write)
Register 56h & 57h: DRAM Bank 0 Configuration
Register 58h & 59h: DRAM Bank 1 Configuration
+ Register 5A:
+ Bit 2: Detrubo
+
+ Register 5C:
+ Bits 7-0: SMRAM base A27-A20
+
+ Register 5D:
+ Bits 3-0: SMRAM base A31-A28
+
Register 60:
Bit 5: If set and SMRAM is enabled, data cycles go to PCI and code cycles go to DRAM
Bit 0: SMRAM Local Access Enable - if set, SMRAM is also enabled outside SMM
@@ -129,14 +136,15 @@ hb4_log(const char *fmt, ...)
#endif
typedef struct hb4_t {
- uint8_t shadow;
- uint8_t shadow_read;
- uint8_t shadow_write;
uint8_t pci_slot;
uint8_t pci_conf[256]; /* PCI Registers */
+
int mem_state[9];
- smram_t *smram[3]; /* SMRAM Handlers */
+
+ uint32_t smram_base;
+
+ smram_t *smram; /* SMRAM Handler */
} hb4_t;
static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY),
@@ -167,7 +175,8 @@ hb4_shadow_bios_low(hb4_t *dev)
{
int state;
- state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)];
+ /* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */
+ state = shadow_bios[dev->pci_conf[0x55] >> 6];
if (state != dev->mem_state[7]) {
mem_set_mem_state_both(0xe0000, 0x10000, state);
@@ -185,7 +194,8 @@ hb4_shadow_main(hb4_t *dev)
int n = 0;
for (uint8_t i = 0; i < 6; i++) {
- state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> (i + 2)) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
+ state = shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] |
+ shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
if (state != dev->mem_state[i + 1]) {
n++;
@@ -202,7 +212,8 @@ hb4_shadow_video(hb4_t *dev)
{
int state;
- state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> 1) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
+ state = shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] |
+ shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
if (state != dev->mem_state[0]) {
mem_set_mem_state_both(0xc0000, 0x8000, state);
@@ -232,22 +243,26 @@ static void
hb4_smram(hb4_t *dev)
{
smram_disable_all();
+ if (dev->smram_base != 0x00000000)
+ umc_smram_recalc(dev->smram_base >> 12, 0);
+
+ dev->smram_base = ((uint32_t) dev->pci_conf[0x5c]) << 20;
+ dev->smram_base |= ((uint32_t) (dev->pci_conf[0x5d] & 0x0f)) << 28;
+ dev->smram_base |= 0x000a0000;
/* Bit 0, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled
in SMM, and is always set to A0000-BFFFF. */
- smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
- /* There's a mirror of the SMRAM at 0E0A0000, mapped to A0000. */
- smram_enable(dev->smram[1], 0x0e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
- /* There's another mirror of the SMRAM at 4E0A0000, mapped to A0000. */
- smram_enable(dev->smram[2], 0x4e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
+ smram_enable(dev->smram, dev->smram_base, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses
this. */
if (dev->pci_conf[0x60] & 0x20) {
if (dev->pci_conf[0x60] & 0x01)
- mem_set_mem_state_smram_ex(0, 0x000a0000, 0x20000, 0x02);
- mem_set_mem_state_smram_ex(1, 0x000a0000, 0x20000, 0x02);
+ mem_set_mem_state_smram_ex(0, dev->smram_base, 0x20000, 0x02);
+ mem_set_mem_state_smram_ex(1, dev->smram_base, 0x20000, 0x02);
}
+
+ umc_smram_recalc(dev->smram_base >> 12, 1);
}
static void
@@ -278,38 +293,27 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv)
cpu_update_waitstates();
break;
- case 0x51:
- case 0x52:
+ case 0x51 ... 0x53:
dev->pci_conf[addr] = val;
break;
- case 0x53:
- dev->pci_conf[addr] = val;
- hb4_log("HB53: %02X\n", val);
- break;
-
- case 0x55:
- dev->shadow_read = (val & 0x80);
- dev->shadow_write = (val & 0x40);
- dev->pci_conf[addr] = val;
- hb4_shadow(dev);
- break;
- case 0x54:
- dev->shadow = (val & 0x01) << 1;
+ case 0x54 ... 0x55:
dev->pci_conf[addr] = val;
hb4_shadow(dev);
break;
- case 0x56 ... 0x5f:
+ case 0x56 ... 0x5b:
+ case 0x5e ... 0x5f:
dev->pci_conf[addr] = val;
break;
+ case 0x5c ... 0x5d:
case 0x60:
dev->pci_conf[addr] = val;
hb4_smram(dev);
break;
- case 0x61:
+ case 0x61 ... 0x62:
dev->pci_conf[addr] = val;
break;
@@ -336,30 +340,35 @@ hb4_reset(void *priv)
hb4_t *dev = (hb4_t *) priv;
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
- dev->pci_conf[0] = 0x60; /* UMC */
- dev->pci_conf[1] = 0x10;
-
- dev->pci_conf[2] = 0x81; /* 8881x */
- dev->pci_conf[3] = 0x88;
-
- dev->pci_conf[7] = 2;
-
- dev->pci_conf[8] = 4;
-
+ dev->pci_conf[0x00] = 0x60; /* UMC */
+ dev->pci_conf[0x01] = 0x10;
+ dev->pci_conf[0x02] = 0x81; /* 8881x */
+ dev->pci_conf[0x03] = 0x88;
+ dev->pci_conf[0x07] = 0x02;
+ dev->pci_conf[0x08] = 0x04;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
-
- dev->pci_conf[0x51] = 1;
- dev->pci_conf[0x52] = 1;
- dev->pci_conf[0x5a] = 4;
- dev->pci_conf[0x5c] = 0xc0;
+ dev->pci_conf[0x50] = 0x00;
+ dev->pci_conf[0x51] = 0x00;
+ dev->pci_conf[0x52] = 0x01;
+ dev->pci_conf[0x53] = 0x00;
+ dev->pci_conf[0x54] = 0x00;
+ dev->pci_conf[0x55] = 0x00;
+ dev->pci_conf[0x56] = 0x00;
+ dev->pci_conf[0x57] = 0x00;
+ dev->pci_conf[0x58] = 0x00;
+ dev->pci_conf[0x59] = 0x00;
+ dev->pci_conf[0x5a] = 0x04;
+ dev->pci_conf[0x5c] = 0x00;
dev->pci_conf[0x5d] = 0x20;
dev->pci_conf[0x5f] = 0xff;
+ dev->pci_conf[0x60] = 0x00;
+ dev->pci_conf[0x61] = 0x00;
+ dev->pci_conf[0x62] = 0x00;
- hb4_write(0, 0x54, 0x00, dev);
- hb4_write(0, 0x55, 0x00, dev);
- hb4_write(0, 0x60, 0x80, dev);
+ hb4_shadow(dev);
+ hb4_smram(dev);
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
@@ -372,6 +381,7 @@ hb4_close(void *priv)
{
hb4_t *dev = (hb4_t *) priv;
+ smram_del(dev->smram);
free(dev);
}
@@ -387,10 +397,9 @@ hb4_init(UNUSED(const device_t *info))
device_add(&port_92_pci_device);
/* SMRAM */
- dev->smram[0] = smram_add();
- dev->smram[1] = smram_add();
- dev->smram[2] = smram_add();
+ dev->smram = smram_add();
+ dev->smram_base = 0x000a0000;
hb4_reset(dev);
return dev;
diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c
index 7c1203c3ab..20e2c7f74f 100644
--- a/src/chipset/via_apollo.c
+++ b/src/chipset/via_apollo.c
@@ -444,7 +444,7 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0);
break;
}
- else
+ else if (dev->id == VIA_595)
switch (val & 0x03) {
case 0x00:
apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0);
@@ -468,6 +468,12 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
default:
break;
}
+ else {
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x00020000,
+ (dev->pci_conf[0x6d] & 0x10) && (dev->pci_conf[0x63] & 0x01),
+ dev->pci_conf[0x63] & 0x01);
+ flushmmucache();
+ }
break;
case 0x65:
if (dev->id == VIA_585)
@@ -532,6 +538,13 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x7f) | (val & 0x7f);
else
dev->pci_conf[0x6d] = val;
+ if (dev->id == VIA_585) {
+ smram_disable_all();
+ smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x00020000,
+ (dev->pci_conf[0x6d] & 0x10) && (dev->pci_conf[0x63] & 0x01),
+ dev->pci_conf[0x63] & 0x01);
+ flushmmucache();
+ }
break;
case 0x6e:
if ((dev->id == VIA_595) || (dev->id == VIA_694))
diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c
index ef076b6060..df8558b053 100644
--- a/src/chipset/wd76c10.c
+++ b/src/chipset/wd76c10.c
@@ -84,6 +84,7 @@ typedef struct
uint8_t bios_states[8];
uint8_t high_bios_states[8];
uint8_t mem_pages[1024];
+ uint8_t ram_state[4192];
uint16_t toggle, cpuclk, fpu_ctl, mem_ctl,
split_sa, sh_wp, hmwpb, npmdmt,
@@ -225,6 +226,34 @@ wd76c10_write_ramw(uint32_t addr, uint16_t val, void *priv)
mem_write_ramw(addr, val, priv);
}
+static void
+wd76c10_set_mem_state(wd76c10_t *dev, uint32_t base, uint32_t size, uint32_t access, uint8_t present)
+{
+ mem_set_mem_state_both(base, size, access);
+
+ for (uint32_t i = base; i < (base + size); i += 4096)
+ dev->ram_state[i >> 12] = present;
+}
+
+static void
+wd76c10_recalc_exec(wd76c10_t *dev, uint32_t base, uint32_t size)
+{
+ uint32_t logical_addr = wd76c10_calc_addr(dev, base);
+ void *exec;
+
+ if (logical_addr != WD76C10_ADDR_INVALID)
+ exec = &(ram[logical_addr]);
+ else
+ exec = NULL;
+
+ for (uint32_t i = base; i < (base + size); i += 4096)
+ if (dev->ram_state[i >> 12])
+ _mem_exec[i >> 12] = exec;
+
+ if (cpu_use_exec)
+ flushmmucache_nopc();
+}
+
static void
wd76c10_banks_recalc(wd76c10_t *dev)
{
@@ -235,6 +264,9 @@ wd76c10_banks_recalc(wd76c10_t *dev)
bit = i + 12;
rb->enable = (dev->split_sa >> bit) & 0x01;
rb->virt_addr = ((uint32_t) dev->bank_bases[i]) << 17;
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size);
}
}
@@ -245,8 +277,12 @@ wd76c10_split_recalc(wd76c10_t *dev)
uint32_t split_size = ((sp_size - 1) * 65536);
ram_bank_t *rb = &(dev->ram_banks[4]);
- if (rb->enable && (rb->virt_size != 0x00000000))
- mem_set_mem_state(rb->virt_addr, rb->virt_size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ if (rb->enable && (rb->virt_size != 0x00000000)) {
+ wd76c10_set_mem_state(dev, rb->virt_addr, rb->virt_size, MEM_READ_EXTANY | MEM_WRITE_EXTANY, 0);
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size);
+ }
rb->virt_addr = ((uint32_t) ((dev->split_sa >> 2) & 0x3f)) << 19;
switch (sp_size) {
case 0x00:
@@ -257,8 +293,12 @@ wd76c10_split_recalc(wd76c10_t *dev)
break;
}
rb->enable = !!sp_size;
- if (rb->enable && (rb->virt_size != 0x00000000))
- mem_set_mem_state(rb->virt_addr, rb->virt_size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ if (rb->enable && (rb->virt_size != 0x00000000)) {
+ wd76c10_set_mem_state(dev, rb->virt_addr, rb->virt_size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL, 1);
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size);
+ }
}
static void
@@ -284,10 +324,13 @@ wd76c10_dis_mem_recalc(wd76c10_t *dev)
}
dev->mem_top = mem_top;
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, 128 * 1024, (640 - 128) * 1024);
}
static void
-wd76c10_shadow_ram_do_recalc(uint8_t *new_st, uint8_t *old_st, uint8_t min, uint8_t max, uint32_t addr)
+wd76c10_shadow_ram_do_recalc(wd76c10_t *dev, uint8_t *new_st, uint8_t *old_st, uint8_t min, uint8_t max, uint32_t addr)
{
uint32_t base = 0x00000000;
int flags = 0;
@@ -300,7 +343,9 @@ wd76c10_shadow_ram_do_recalc(uint8_t *new_st, uint8_t *old_st, uint8_t min, uint
((new_st[i] & 0x04) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL);
flags |= (new_st[i] & 0x02) ? MEM_WRITE_INTERNAL :
((new_st[i] & 0x04) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL);
- mem_set_mem_state_both(base, 0x00004000, flags);
+ wd76c10_set_mem_state(dev, base, 0x00004000, flags, new_st[i] & 0x01);
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, base, 0x000040000);
}
}
}
@@ -366,11 +411,11 @@ wd76c10_shadow_ram_recalc(wd76c10_t *dev)
break;
}
- wd76c10_shadow_ram_do_recalc(vbios_states, dev->vbios_states, 0, 4, 0x000c0000);
- wd76c10_shadow_ram_do_recalc(bios_states, dev->bios_states, 0, 8, 0x000e0000);
+ wd76c10_shadow_ram_do_recalc(dev, vbios_states, dev->vbios_states, 0, 4, 0x000c0000);
+ wd76c10_shadow_ram_do_recalc(dev, bios_states, dev->bios_states, 0, 8, 0x000e0000);
/* This is not shadowed, but there is a CSPROM# (= ROMCS#) toggle. */
- wd76c10_shadow_ram_do_recalc(high_bios_states, dev->high_bios_states, 0, 8, 0x00fe0000);
+ wd76c10_shadow_ram_do_recalc(dev, high_bios_states, dev->high_bios_states, 0, 8, 0x00fe0000);
flushmmucache_nopc();
}
@@ -385,9 +430,15 @@ wd76c10_high_mem_wp_recalc(wd76c10_t *dev)
/* ACCESS_NORMAL means both ACCESS_BUS and ACCESS_CPU are set. */
mem_set_wp(dev->hmwp_base, size, ACCESS_NORMAL, 0);
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, dev->hmwp_base, size);
+
size = 0x01000000 - base;
mem_set_wp(base, size, ACCESS_NORMAL, hm_wp);
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, base, size);
+
dev->hmwp_base = base;
}
@@ -399,7 +450,10 @@ wd76c10_pf_loc_reset(wd76c10_t *dev)
for (uint8_t i = 0x031; i <= 0x03b; i++) {
dev->mem_pages[i] = 0xff;
base = ((uint32_t) i) << 14;
- mem_set_mem_state(base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
+ wd76c10_set_mem_state(dev, base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY, 0);
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, base, 0x00004000);
}
/* Re-apply any ROMCS#, etc. flags. */
@@ -419,9 +473,13 @@ wd76c10_pf_loc_recalc(wd76c10_t *dev)
dev->mem_pages[i] = ems_page;
base = ((uint32_t) i) << 14;
dev->ems_pages[ems_page].virt = base;
- if ((ems_en >= 0x02) && dev->ems_pages[ems_page].enabled)
- mem_set_mem_state(dev->ems_pages[ems_page].virt, 0x00004000,
- MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
+ if ((ems_en >= 0x02) && dev->ems_pages[ems_page].enabled) {
+ wd76c10_set_mem_state(dev, dev->ems_pages[ems_page].virt,
+ 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL, 1);
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, dev->ems_pages[ems_page].virt, 0x00004000);
+ }
}
}
@@ -436,6 +494,9 @@ wd76c10_low_pages_recalc(wd76c10_t *dev)
dev->mem_pages[i] = ems_page;
base = ((uint32_t) i) << 14;
dev->ems_pages[ems_page].virt = base;
+
+ if (cpu_use_exec)
+ wd76c10_recalc_exec(dev, dev->ems_pages[ems_page].virt, 0x00004000);
}
}
@@ -948,6 +1009,8 @@ wd76c10_init(const device_t *info)
mem_mapping_disable(&ram_high_mapping);
mem_mapping_enable(&dev->ram_mapping);
+ memset(dev->ram_state, 0x00, sizeof(dev->ram_state));
+
return dev;
}
diff --git a/src/codegen/codegen_ops.c b/src/codegen/codegen_ops.c
index a81eef67e1..c8e258e788 100644
--- a/src/codegen/codegen_ops.c
+++ b/src/codegen/codegen_ops.c
@@ -12,6 +12,7 @@
#include "x86_flags.h"
#include "x86seg_common.h"
#include "x86seg.h"
+#include "x87_sf.h"
#include "x87.h"
#include "386_common.h"
#include "cpu.h"
diff --git a/src/codegen/codegen_ops_fpu.h b/src/codegen/codegen_ops_fpu.h
index 1021cc7426..242743dee1 100644
--- a/src/codegen/codegen_ops_fpu.h
+++ b/src/codegen/codegen_ops_fpu.h
@@ -671,9 +671,10 @@ ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeb
ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
static double fp_imm = v; \
+ static uint64_t *fptr = (uint64_t *) &fp_imm; \
\
FP_ENTER(); \
- FP_LOAD_IMM_Q(*(uint64_t *) &fp_imm); \
+ FP_LOAD_IMM_Q(*fptr); \
\
return op_pc; \
}
diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h
index bc6293c0bf..08b9ee5f24 100644
--- a/src/codegen/codegen_ops_x86-64.h
+++ b/src/codegen/codegen_ops_x86-64.h
@@ -4434,7 +4434,7 @@ FP_COMPARE_REG(int dst, int src)
addbyte((uint8_t) cpu_state_offset(npxs) + 1);
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
addbyte(0xe1);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
if (src) {
addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/
@@ -4467,7 +4467,7 @@ FP_COMPARE_REG(int dst, int src)
addbyte(0x9f); /*LAHF*/
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
@@ -4493,7 +4493,7 @@ FP_COMPARE_MEM(void)
addbyte((uint8_t) cpu_state_offset(ST));
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
addbyte(0xe1);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0x66); /*COMISD XMM0, XMM1*/
addbyte(0x0f);
addbyte(0x2f);
@@ -4501,7 +4501,7 @@ FP_COMPARE_MEM(void)
addbyte(0x9f); /*LAHF*/
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h
index 410ce8e17a..c48324c2a9 100644
--- a/src/codegen/codegen_ops_x86.h
+++ b/src/codegen/codegen_ops_x86.h
@@ -2911,7 +2911,7 @@ FP_COMPARE_S(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xd8); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -2919,7 +2919,7 @@ FP_COMPARE_S(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -2943,7 +2943,7 @@ FP_COMPARE_S(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xd8); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -2951,7 +2951,7 @@ FP_COMPARE_S(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -2980,7 +2980,7 @@ FP_COMPARE_D(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xdc); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -2988,7 +2988,7 @@ FP_COMPARE_D(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -3016,7 +3016,7 @@ FP_COMPARE_D(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xdc); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -3024,7 +3024,7 @@ FP_COMPARE_D(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -3050,7 +3050,7 @@ FP_COMPARE_IW(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xde); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -3058,7 +3058,7 @@ FP_COMPARE_IW(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -3082,7 +3082,7 @@ FP_COMPARE_IW(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xde); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -3090,7 +3090,7 @@ FP_COMPARE_IW(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -3115,7 +3115,7 @@ FP_COMPARE_IL(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xda); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -3123,7 +3123,7 @@ FP_COMPARE_IL(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -3147,7 +3147,7 @@ FP_COMPARE_IL(void)
addbyte(0xe2);
addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/
addbyte(0xe3);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xda); /*FCOMP [ESP]*/
addbyte(0x04 | 0x18);
addbyte(0x24);
@@ -3155,7 +3155,7 @@ FP_COMPARE_IL(void)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR BL, AH*/
addbyte(0xe3);
addbyte(0x88); /*MOV [npxs+1], BL*/
@@ -3250,7 +3250,7 @@ FP_COMPARE_REG(int dst, int src)
addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7]));
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
addbyte(0xe1);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
addbyte(0xdc); /*FCOMP ST[src][EBP]*/
addbyte(0x5d);
addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7]));
@@ -3258,7 +3258,7 @@ FP_COMPARE_REG(int dst, int src)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
@@ -3286,7 +3286,7 @@ FP_COMPARE_REG(int dst, int src)
addbyte(0xe2);
addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/
addbyte(0xe1);
- addbyte((~(C0 | C2 | C3)) >> 8);
+ addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8);
if (src) {
addbyte(0xdd); /*FLD ST[EBX*8]*/
@@ -3312,7 +3312,7 @@ FP_COMPARE_REG(int dst, int src)
addbyte(0xe0);
addbyte(0x80); /*AND AH, (C0|C2|C3)*/
addbyte(0xe4);
- addbyte((C0 | C2 | C3) >> 8);
+ addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8);
addbyte(0x08); /*OR CL, AH*/
addbyte(0xe1);
addbyte(0x88); /*MOV [npxs+1], CL*/
diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c
index 421f200262..9588721623 100644
--- a/src/codegen/codegen_x86-64.c
+++ b/src/codegen/codegen_x86-64.c
@@ -13,6 +13,7 @@
# include "x86_ops.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
# include <86box/mem.h>
# include <86box/plat_unused.h>
diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c
index 456f93ae9b..74c209001b 100644
--- a/src/codegen/codegen_x86.c
+++ b/src/codegen/codegen_x86.c
@@ -51,6 +51,7 @@
# include "x86_ops.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
/*ex*/
# include <86box/nmi.h>
diff --git a/src/codegen_new/codegen_backend_arm.c b/src/codegen_new/codegen_backend_arm.c
index b1e904096c..9c480dccf6 100644
--- a/src/codegen_new/codegen_backend_arm.c
+++ b/src/codegen_new/codegen_backend_arm.c
@@ -15,6 +15,7 @@
# include "x86.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
# if defined(__linux__) || defined(__APPLE__)
diff --git a/src/codegen_new/codegen_backend_arm64.c b/src/codegen_new/codegen_backend_arm64.c
index 1eb94a9090..5c2233b635 100644
--- a/src/codegen_new/codegen_backend_arm64.c
+++ b/src/codegen_new/codegen_backend_arm64.c
@@ -15,6 +15,7 @@
# include "x86.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
# if defined(__linux__) || defined(__APPLE__)
diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c
index 7514e1f0c3..deaf53c200 100644
--- a/src/codegen_new/codegen_backend_arm64_uops.c
+++ b/src/codegen_new/codegen_backend_arm64_uops.c
@@ -9,6 +9,7 @@
# include "x86.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
# include "386_common.h"
# include "codegen.h"
@@ -648,10 +649,10 @@ codegen_FTST(codeblock_t *block, uop_t *uop)
host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP);
host_arm64_MOVZ_IMM(block, dest_reg, 0);
host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP);
- host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3);
- host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0);
+ host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C3);
+ host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, FPU_SW_C0);
host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg);
- host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3);
+ host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg);
host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg);
} else
@@ -690,10 +691,10 @@ codegen_FCOM(codeblock_t *block, uop_t *uop)
if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) {
host_arm64_MOVZ_IMM(block, dest_reg, 0);
host_arm64_FCMP_D(block, src_reg_a, src_reg_b);
- host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3);
- host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0);
+ host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C3);
+ host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, FPU_SW_C0);
host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg);
- host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3);
+ host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg);
host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg);
} else
diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c
index 338d3dd546..d8c2238845 100644
--- a/src/codegen_new/codegen_backend_arm_uops.c
+++ b/src/codegen_new/codegen_backend_arm_uops.c
@@ -10,6 +10,7 @@
# include "x86.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
# include "386_common.h"
# include "codegen.h"
@@ -718,9 +719,9 @@ codegen_FTST(codeblock_t *block, uop_t *uop)
host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP);
host_arm_MOV_IMM(block, dest_reg, 0);
host_arm_VMRS_APSR(block);
- host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3);
- host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0);
- host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3);
+ host_arm_ORREQ_IMM(block, dest_reg, dest_reg, FPU_SW_C3);
+ host_arm_ORRCC_IMM(block, dest_reg, dest_reg, FPU_SW_C0);
+ host_arm_ORRVS_IMM(block, dest_reg, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
} else
fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
@@ -758,9 +759,9 @@ codegen_FCOM(codeblock_t *block, uop_t *uop)
host_arm_VCMP_D(block, src_reg_a, src_reg_b);
host_arm_MOV_IMM(block, dest_reg, 0);
host_arm_VMRS_APSR(block);
- host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3);
- host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0);
- host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3);
+ host_arm_ORREQ_IMM(block, dest_reg, dest_reg, FPU_SW_C3);
+ host_arm_ORRCC_IMM(block, dest_reg, dest_reg, FPU_SW_C0);
+ host_arm_ORRVS_IMM(block, dest_reg, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
} else
fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c
index fcab0f3ce8..46af68e751 100644
--- a/src/codegen_new/codegen_backend_x86-64_uops.c
+++ b/src/codegen_new/codegen_backend_x86-64_uops.c
@@ -9,6 +9,7 @@
# include "x86.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "x87.h"
# include "386_common.h"
# include "codegen.h"
@@ -672,7 +673,7 @@ codegen_FTST(codeblock_t *block, uop_t *uop)
host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX);
host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP);
host_x86_LAHF(block);
- host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3);
+ host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
if (dest_reg != REG_EAX) {
host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX);
host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX);
@@ -720,7 +721,7 @@ codegen_FCOM(codeblock_t *block, uop_t *uop)
host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX);
host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b);
host_x86_LAHF(block);
- host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3);
+ host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
if (dest_reg != REG_EAX) {
host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX);
host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX);
diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c
index 5ef2d97b8a..cd79b9b47e 100644
--- a/src/codegen_new/codegen_backend_x86_uops.c
+++ b/src/codegen_new/codegen_backend_x86_uops.c
@@ -10,6 +10,7 @@
# include "x86_ops.h"
# include "x86seg_common.h"
# include "x86seg.h"
+# include "x87_sf.h"
# include "386_common.h"
# include "codegen.h"
# include "codegen_allocator.h"
@@ -677,7 +678,7 @@ codegen_FTST(codeblock_t *block, uop_t *uop)
host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX);
host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP);
host_x86_LAHF(block);
- host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3);
+ host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
if (dest_reg != REG_EAX) {
host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX);
host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX);
@@ -725,7 +726,7 @@ codegen_FCOM(codeblock_t *block, uop_t *uop)
host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX);
host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b);
host_x86_LAHF(block);
- host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3);
+ host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3);
if (dest_reg != REG_EAX) {
host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX);
host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX);
diff --git a/src/codegen_new/codegen_block.c b/src/codegen_new/codegen_block.c
index ee0a030ba9..a8ea0e06e6 100644
--- a/src/codegen_new/codegen_block.c
+++ b/src/codegen_new/codegen_block.c
@@ -12,6 +12,7 @@
#include "x86_ops.h"
#include "x86seg_common.h"
#include "x86seg.h"
+#include "x87_sf.h"
#include "x87.h"
#include "386_common.h"
diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c
index 3ab7be8ac9..a7b5290f4e 100644
--- a/src/codegen_new/codegen_ops_fpu_arith.c
+++ b/src/codegen_new/codegen_ops_fpu_arith.c
@@ -9,6 +9,7 @@
#include "x86seg_common.h"
#include "x86seg.h"
#include "386_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
@@ -59,7 +60,7 @@ ropFCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
@@ -71,7 +72,7 @@ ropFCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP(block, ir);
@@ -82,7 +83,7 @@ ropFCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe
{
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP2(block, ir);
@@ -269,7 +270,7 @@ ropFUCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
@@ -281,7 +282,7 @@ ropFUCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP(block, ir);
@@ -292,7 +293,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f
{
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP2(block, ir);
@@ -328,7 +329,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
\
return op_pc + 1; \
@@ -344,7 +345,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
fpu_POP(block, ir); \
\
@@ -460,7 +461,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE)
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
\
return op_pc + 1; \
@@ -477,7 +478,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE)
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
fpu_POP(block, ir); \
\
@@ -600,7 +601,7 @@ ropFTST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3
{
uop_FP_ENTER(ir);
uop_FTST(ir, IREG_temp0_W, IREG_ST(0));
- uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3));
+ uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
diff --git a/src/codegen_new/codegen_ops_fpu_constant.c b/src/codegen_new/codegen_ops_fpu_constant.c
index 8628458687..a91d675c5d 100644
--- a/src/codegen_new/codegen_ops_fpu_constant.c
+++ b/src/codegen_new/codegen_ops_fpu_constant.c
@@ -9,6 +9,7 @@
#include "x86seg_common.h"
#include "x86seg.h"
#include "386_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
diff --git a/src/codegen_new/codegen_ops_fpu_loadstore.c b/src/codegen_new/codegen_ops_fpu_loadstore.c
index 7635063e86..12babaf49d 100644
--- a/src/codegen_new/codegen_ops_fpu_loadstore.c
+++ b/src/codegen_new/codegen_ops_fpu_loadstore.c
@@ -9,6 +9,7 @@
#include "x86seg_common.h"
#include "x86seg.h"
#include "386_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
diff --git a/src/codegen_new/codegen_ops_fpu_misc.c b/src/codegen_new/codegen_ops_fpu_misc.c
index 7865e05730..31b668488e 100644
--- a/src/codegen_new/codegen_ops_fpu_misc.c
+++ b/src/codegen_new/codegen_ops_fpu_misc.c
@@ -9,6 +9,7 @@
#include "x86seg_common.h"
#include "x86seg.h"
#include "386_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
diff --git a/src/config.c b/src/config.c
index 7bf29155cc..ab23ddb4fe 100644
--- a/src/config.c
+++ b/src/config.c
@@ -77,6 +77,7 @@
#include <86box/plat_dir.h>
#include <86box/ui.h>
#include <86box/snd_opl.h>
+#include <86box/version.h>
static int cx;
static int cy;
@@ -139,8 +140,6 @@ load_general(void)
rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0);
update_icons = ini_section_get_int(cat, "update_icons", 1);
- status_icons_fullscreen = !!ini_section_get_int(cat, "status_icons_fullscreen", 0);
-
window_remember = ini_section_get_int(cat, "window_remember", 0);
if (!window_remember && !(vid_resize & 2))
@@ -211,6 +210,12 @@ load_general(void)
ini_section_delete_var(cat, "window_coordinates");
do_auto_pause = ini_section_get_int(cat, "do_auto_pause", 0);
+
+ p = ini_section_get_string(cat, "uuid", NULL);
+ if (p != NULL)
+ strncpy(uuid, p, sizeof(uuid) - 1);
+ else
+ strncpy(uuid, "", sizeof(uuid) - 1);
}
/* Load monitor section. */
@@ -244,25 +249,82 @@ load_machine(void)
{
ini_section_t cat = ini_find_section(config, "Machine");
const char *p;
+ const char *migrate_from = NULL;
int c;
int i;
+ int j;
int speed;
double multi;
p = ini_section_get_string(cat, "machine", NULL);
- if (p != NULL)
- machine = machine_get_machine_from_internal_name(p);
- else
+ if (p != NULL) {
+ migrate_from = p;
+ /* Migrate renamed machines. */
+ if (!strcmp(p, "430nx"))
+ machine = machine_get_machine_from_internal_name("586ip");
+ else if (!strcmp(p, "586mc1"))
+ machine = machine_get_machine_from_internal_name("586is");
+ else {
+ machine = machine_get_machine_from_internal_name(p);
+ migrate_from = NULL;
+ }
+ } else
machine = 0;
if (machine >= machine_count())
machine = machine_count() - 1;
- cpu_override = ini_section_get_int(cat, "cpu_override", 0);
- cpu_f = NULL;
- p = ini_section_get_string(cat, "cpu_family", NULL);
+ /* Copy NVR files when migrating a machine to a new internal name. */
+ if (migrate_from) {
+ char old_fn[256];
+ strcpy(old_fn, migrate_from);
+ strcat(old_fn, ".");
+ c = strlen(old_fn);
+ char new_fn[256];
+ strcpy(new_fn, machines[machine].internal_name);
+ strcat(new_fn, ".");
+ i = strlen(new_fn);
+
+ /* Iterate through NVR files. */
+ DIR *dirp = opendir(nvr_path("."));
+ if (dirp) {
+ struct dirent *entry;
+ while ((entry = readdir(dirp))) {
+ /* Check if this file corresponds to the old name. */
+ if (strncmp(entry->d_name, old_fn, c))
+ continue;
+
+ /* Add extension to the new name. */
+ strcpy(&new_fn[i], &entry->d_name[c]);
+
+ /* Only copy if a file with the new name doesn't already exist. */
+ FILE *g = nvr_fopen(new_fn, "rb");
+ if (!g) {
+ FILE *f = nvr_fopen(entry->d_name, "rb");
+ g = nvr_fopen(new_fn, "wb");
+
+ uint8_t buf[4096];
+ while ((j = fread(buf, 1, sizeof(buf), f)))
+ fwrite(buf, 1, j, g);
+
+ fclose(f);
+ }
+ fclose(g);
+ }
+ }
+ }
+
+ cpu_override = ini_section_get_int(cat, "cpu_override", 0);
+ cpu_override_interpreter = ini_section_get_int(cat, "cpu_override_interpreter", 0);
+ cpu_f = NULL;
+ p = ini_section_get_string(cat, "cpu_family", NULL);
if (p) {
- cpu_f = cpu_get_family(p);
+ /* Migrate CPU family changes. */
+ if ((!strcmp(machines[machine].internal_name, "deskpro386") ||
+ !strcmp(machines[machine].internal_name, "deskpro386_05_1988")))
+ cpu_f = cpu_get_family("i386dx_deskpro386");
+ else
+ cpu_f = cpu_get_family(p);
if (cpu_f && !cpu_family_is_eligible(cpu_f, machine)) /* only honor eligible families */
cpu_f = NULL;
@@ -609,9 +671,9 @@ load_network(void)
if (nc->net_type == NET_TYPE_PCAP) {
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
if (network_ndev == 1)
- ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130);
+ ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_NO_DEVICES), plat_get_string(STRING_PCAP_ERROR_DESC));
else if (network_dev_to_id(p) == -1)
- ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130);
+ ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_INVALID_DEVICE), plat_get_string(STRING_PCAP_ERROR_DESC));
strcpy(nc->host_dev_name, "none");
} else
strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1);
@@ -656,9 +718,9 @@ load_network(void)
if (nc->net_type == NET_TYPE_PCAP) {
if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) {
if (network_ndev == 1)
- ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130);
+ ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_NO_DEVICES), plat_get_string(STRING_PCAP_ERROR_DESC));
else if (network_dev_to_id(p) == -1)
- ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130);
+ ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_PCAP_ERROR_INVALID_DEVICE), plat_get_string(STRING_PCAP_ERROR_DESC));
strcpy(nc->host_dev_name, "none");
} else
strncpy(nc->host_dev_name, p, sizeof(nc->host_dev_name) - 1);
@@ -683,7 +745,6 @@ load_ports(void)
char *p;
char temp[512];
int c;
- int d;
memset(temp, 0, sizeof(temp));
@@ -706,14 +767,6 @@ load_ports(void)
p = ini_section_get_string(cat, temp, "none");
lpt_ports[c].device = lpt_device_get_from_internal_name(p);
}
-
- /* Legacy config compatibility. */
- d = ini_section_get_int(cat, "lpt_enabled", 2);
- if (d < 2) {
- for (c = 0; c < PARALLEL_MAX; c++)
- lpt_ports[c].enabled = d;
- }
- ini_section_delete_var(cat, "lpt_enabled");
}
/* Load "Storage Controllers" section. */
@@ -721,13 +774,14 @@ static void
load_storage_controllers(void)
{
ini_section_t cat = ini_find_section(config, "Storage controllers");
+ ini_section_t migration_cat;
char *p;
char temp[512];
int c;
int min = 0;
int free_p = 0;
- for (c = min; c < SCSI_BUS_MAX; c++) {
+ for (c = min; c < SCSI_CARD_MAX; c++) {
sprintf(temp, "scsicard_%d", c + 1);
p = ini_section_get_string(cat, temp, NULL);
@@ -754,17 +808,16 @@ load_storage_controllers(void)
}
free_p = 1;
}
- if (!strcmp(p, "mfm_xt"))
- hdc_current = hdc_get_from_internal_name("st506_xt");
- else if (!strcmp(p, "mfm_xt_dtc5150x"))
- hdc_current = hdc_get_from_internal_name("st506_xt_dtc5150x");
- else if (!strcmp(p, "mfm_at"))
- hdc_current = hdc_get_from_internal_name("st506_at");
- else if (!strcmp(p, "vlb_isa"))
- hdc_current = hdc_get_from_internal_name("ide_vlb");
- else if (!strcmp(p, "vlb_isa_2ch"))
- hdc_current = hdc_get_from_internal_name("ide_vlb_2ch");
- else
+ /* Migrate renamed and merged cards. */
+ if (!strcmp(p, "xtide_plus")) {
+ hdc_current = hdc_get_from_internal_name("xtide");
+ migration_cat = ini_find_or_create_section(config, "PC/XT XTIDE");
+ ini_section_set_string(migration_cat, "bios", "xt_plus");
+ } else if (!strcmp(p, "xtide_at_386")) {
+ hdc_current = hdc_get_from_internal_name("xtide_at");
+ migration_cat = ini_find_or_create_section(config, "PC/AT XTIDE");
+ ini_section_set_string(migration_cat, "bios", "at_386");
+ } else
hdc_current = hdc_get_from_internal_name(p);
if (free_p) {
@@ -822,6 +875,8 @@ load_storage_controllers(void)
path_normalize(cart_fns[c]);
}
}
+
+ lba_enhancer_enabled = !!ini_section_get_int(cat, "lba_enhancer_enabled", 0);
}
/* Load "Hard Disks" section. */
@@ -1120,8 +1175,7 @@ load_floppy_and_cdrom_drives(void)
memset(temp, 0x00, sizeof(temp));
for (c = 0; c < CDROM_NUM; c++) {
sprintf(temp, "cdrom_%02i_host_drive", c + 1);
- cdrom[c].host_drive = ini_section_get_int(cat, temp, 0);
- cdrom[c].prev_host_drive = cdrom[c].host_drive;
+ ini_section_delete_var(cat, temp);
sprintf(temp, "cdrom_%02i_parameters", c + 1);
p = ini_section_get_string(cat, temp, NULL);
@@ -1208,12 +1262,6 @@ load_floppy_and_cdrom_drives(void)
path_normalize(cdrom[c].image_path);
}
- if (cdrom[c].host_drive && (cdrom[c].host_drive != 200))
- cdrom[c].host_drive = 0;
-
- if ((cdrom[c].host_drive == 0x200) && (strlen(cdrom[c].image_path) == 0))
- cdrom[c].host_drive = 0;
-
for (int i = 0; i < MAX_PREV_IMAGES; i++) {
cdrom[c].image_history[i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char));
sprintf(temp, "cdrom_%02i_image_history_%02i", c + 1, i + 1);
@@ -1234,9 +1282,6 @@ load_floppy_and_cdrom_drives(void)
/* If the CD-ROM is disabled, delete all its variables. */
if (cdrom[c].bus_type == CDROM_BUS_DISABLED) {
- sprintf(temp, "cdrom_%02i_host_drive", c + 1);
- ini_section_delete_var(cat, temp);
-
sprintf(temp, "cdrom_%02i_parameters", c + 1);
ini_section_delete_var(cat, temp);
@@ -1367,9 +1412,6 @@ load_other_removable_devices(void)
/* If the ZIP drive is disabled, delete all its variables. */
if (zip_drives[c].bus_type == ZIP_BUS_DISABLED) {
- sprintf(temp, "zip_%02i_host_drive", c + 1);
- ini_section_delete_var(cat, temp);
-
sprintf(temp, "zip_%02i_parameters", c + 1);
ini_section_delete_var(cat, temp);
@@ -1483,9 +1525,6 @@ load_other_removable_devices(void)
/* If the MO drive is disabled, delete all its variables. */
if (mo_drives[c].bus_type == MO_BUS_DISABLED) {
- sprintf(temp, "mo_%02i_host_drive", c + 1);
- ini_section_delete_var(cat, temp);
-
sprintf(temp, "mo_%02i_parameters", c + 1);
ini_section_delete_var(cat, temp);
@@ -1514,9 +1553,10 @@ load_other_peripherals(void)
char *p;
char temp[512];
- bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0);
- postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0);
- unittester_enabled = !!ini_section_get_int(cat, "unittester_enabled", 0);
+ bugger_enabled = !!ini_section_get_int(cat, "bugger_enabled", 0);
+ postcard_enabled = !!ini_section_get_int(cat, "postcard_enabled", 0);
+ unittester_enabled = !!ini_section_get_int(cat, "unittester_enabled", 0);
+ novell_keycard_enabled = !!ini_section_get_int(cat, "novell_keycard_enabled", 0);
for (uint8_t c = 0; c < ISAMEM_MAX; c++) {
sprintf(temp, "isamem%d_type", c);
@@ -1562,6 +1602,8 @@ config_load(void)
dpi_scale = 1;
do_auto_pause = 0;
+ cpu_override_interpreter = 0;
+
fpu_type = fpu_get_type(cpu_f, cpu, "none");
gfxcard[0] = video_get_video_from_internal_name("cga");
vid_api = plat_vidapi("default");
@@ -1803,11 +1845,6 @@ save_general(void)
else
ini_section_delete_var(cat, "open_dir_usr_path");
- if (status_icons_fullscreen)
- ini_section_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen);
- else
- ini_section_delete_var(cat, "status_icons_fullscreen");
-
if (video_framerate != -1)
ini_section_set_int(cat, "video_gl_framerate", video_framerate);
else
@@ -1826,6 +1863,20 @@ save_general(void)
else
ini_section_delete_var(cat, "do_auto_pause");
+ char cpu_buf[128] = { 0 };
+ plat_get_cpu_string(cpu_buf, 128);
+ ini_section_set_string(cat, "host_cpu", cpu_buf);
+
+ if (EMU_BUILD_NUM != 0)
+ ini_section_set_int(cat, "emu_build_num", EMU_BUILD_NUM);
+ else
+ ini_section_delete_var(cat, "emu_build_num");
+
+ if (strnlen(uuid, sizeof(uuid) - 1) > 0)
+ ini_section_set_string(cat, "uuid", uuid);
+ else
+ ini_section_delete_var(cat, "uuid");
+
ini_delete_section_if_empty(config, cat);
}
@@ -1864,11 +1915,6 @@ save_machine(void)
{
ini_section_t cat = ini_find_or_create_section(config, "Machine");
const char *p;
- int c;
- int i = 0;
- int legacy_mfg;
- int legacy_cpu = -1;
- int closest_legacy_cpu = -1;
p = machine_get_internal_name();
ini_section_set_string(cat, "machine", p);
@@ -1880,62 +1926,15 @@ save_machine(void)
ini_section_set_int(cat, "cpu_override", cpu_override);
else
ini_section_delete_var(cat, "cpu_override");
+ if (cpu_override_interpreter)
+ ini_section_set_int(cat, "cpu_override_interpreter", cpu_override_interpreter);
+ else
+ ini_section_delete_var(cat, "cpu_override_interpreter");
/* Downgrade compatibility with the previous CPU model system. */
ini_section_delete_var(cat, "cpu_manufacturer");
ini_section_delete_var(cat, "cpu");
- /* Look for a machine entry on the legacy table. */
- c = 0;
- while (cpu_legacy_table[c].machine) {
- if (!strcmp(p, cpu_legacy_table[c].machine))
- break;
- c++;
- }
- if (cpu_legacy_table[c].machine) {
- /* Look for a corresponding CPU entry. */
- const cpu_legacy_table_t *legacy_table_entry;
- for (legacy_mfg = 0; legacy_mfg < 4; legacy_mfg++) {
- if (!cpu_legacy_table[c].tables[legacy_mfg])
- continue;
-
- i = 0;
- while (cpu_legacy_table[c].tables[legacy_mfg][i].family) {
- legacy_table_entry = &cpu_legacy_table[c].tables[legacy_mfg][i];
-
- /* Match the family name, speed and multiplier. */
- if (!strcmp(cpu_f->internal_name, legacy_table_entry->family)) {
- if ((legacy_table_entry->rspeed == cpu_f->cpus[cpu].rspeed) &&
- (legacy_table_entry->multi == cpu_f->cpus[cpu].multi)) {
- /* Exact speed/multiplier match. */
- legacy_cpu = i;
- break;
- } else if ((legacy_table_entry->rspeed >= cpu_f->cpus[cpu].rspeed) &&
- (closest_legacy_cpu == -1))
- /* Closest speed match. */
- closest_legacy_cpu = i;
- }
-
- i++;
- }
-
- /* Use the closest speed match if no exact match was found. */
- if ((legacy_cpu == -1) && (closest_legacy_cpu > -1)) {
- legacy_cpu = closest_legacy_cpu;
- break;
- } else if (legacy_cpu > -1) /* exact match found */
- break;
- }
-
- /* Set legacy values if a match was found. */
- if (legacy_cpu > -1) {
- if (legacy_mfg)
- ini_section_set_int(cat, "cpu_manufacturer", legacy_mfg);
- if (legacy_cpu)
- ini_section_set_int(cat, "cpu", legacy_cpu);
- }
- }
-
if (cpu_waitstates == 0)
ini_section_delete_var(cat, "cpu_waitstates");
else
@@ -2264,7 +2263,7 @@ save_storage_controllers(void)
ini_section_delete_var(cat, "scsicard");
- for (c = 0; c < SCSI_BUS_MAX; c++) {
+ for (c = 0; c < SCSI_CARD_MAX; c++) {
sprintf(temp, "scsicard_%d", c + 1);
if (scsi_card_current[c] == 0)
@@ -2348,6 +2347,11 @@ save_storage_controllers(void)
else
ini_section_set_string(cat, temp, cart_fns[c]);
}
+
+ if (lba_enhancer_enabled == 0)
+ ini_section_delete_var(cat, "lba_enhancer_enabled");
+ else
+ ini_section_set_int(cat, "lba_enhancer_enabled", 1);
}
/* Save "Other Peripherals" section. */
@@ -2372,6 +2376,11 @@ save_other_peripherals(void)
else
ini_section_set_int(cat, "unittester_enabled", unittester_enabled);
+ if (novell_keycard_enabled == 0)
+ ini_section_delete_var(cat, "novell_keycard_enabled");
+ else
+ ini_section_set_int(cat, "novell_keycard_enabled", novell_keycard_enabled);
+
for (uint8_t c = 0; c < ISAMEM_MAX; c++) {
sprintf(temp, "isamem%d_type", c);
if (isamem_type[c] == 0)
@@ -2550,10 +2559,7 @@ save_floppy_and_cdrom_drives(void)
for (c = 0; c < CDROM_NUM; c++) {
sprintf(temp, "cdrom_%02i_host_drive", c + 1);
- if ((cdrom[c].bus_type == 0) || (cdrom[c].host_drive != 200))
- ini_section_delete_var(cat, temp);
- else
- ini_section_set_int(cat, temp, cdrom[c].host_drive);
+ ini_section_delete_var(cat, temp);
sprintf(temp, "cdrom_%02i_speed", c + 1);
if ((cdrom[c].bus_type == 0) || (cdrom[c].speed == 8))
diff --git a/src/cpu/386.c b/src/cpu/386.c
index b5a1e61e3b..3e96911ba7 100644
--- a/src/cpu/386.c
+++ b/src/cpu/386.c
@@ -15,6 +15,7 @@
#include "x86.h"
#include "x86_ops.h"
#include "x86seg_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include <86box/io.h>
#include <86box/nmi.h>
@@ -25,6 +26,7 @@
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/machine.h>
+#include <86box/plat_fallthrough.h>
#include <86box/gdbstub.h>
#ifndef OPS_286_386
# define OPS_286_386
@@ -262,11 +264,10 @@ exec386_2386(int32_t cycs)
CHECK_READ_CS(MIN(ol, 4));
ins_fetch_fault = cpu_386_check_instruction_fault();
- if (!cpu_state.abrt && ins_fetch_fault) {
- x86gen();
+ /* Breakpoint fault has priority over other faults. */
+ if (ins_fetch_fault) {
ins_fetch_fault = 0;
- /* No instructions executed at this point. */
- goto block_ended;
+ cpu_state.abrt = 1;
}
if (!cpu_state.abrt) {
@@ -279,7 +280,11 @@ exec386_2386(int32_t cycs)
trap |= !!(cpu_state.flags & T_FLAG);
cpu_state.pc++;
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+ cpu_state.eflags &= ~(RF_FLAG);
+ if (opcode == 0xf0)
+ in_lock = 1;
+ x86_2386_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+ in_lock = 0;
if (x86_was_reset)
break;
}
@@ -296,7 +301,6 @@ exec386_2386(int32_t cycs)
if (cpu_end_block_after_ins)
cpu_end_block_after_ins--;
-block_ended:
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
@@ -319,8 +323,6 @@ exec386_2386(int32_t cycs)
#endif
}
}
- if (!x86_was_reset && ins_fetch_fault)
- x86gen(); /* This is supposed to be the first one serviced by the processor according to the manual. */
} else if (trap) {
flags_rebuild();
if (trap & 2) dr[6] |= 0x8000;
diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c
index 4b40372075..d1d38006b2 100644
--- a/src/cpu/386_common.c
+++ b/src/cpu/386_common.c
@@ -14,6 +14,7 @@
#include <86box/timer.h>
#include "x86.h"
#include "x86seg_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include <86box/nmi.h>
#include <86box/mem.h>
@@ -50,6 +51,8 @@ uint32_t dr[8];
uint32_t use32;
int stack32;
+int cpu_init = 0;
+
uint32_t *eal_r;
uint32_t *eal_w;
@@ -120,6 +123,53 @@ int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /*
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
+/* 0 = no, 1 = always, 2 = depends on second opcode, 3 = depends on mod/rm */
+int lock_legal[256] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 2, /* 0x0x */
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x1x */
+ 1, 1, 1, 1, 1, 1, 4, 0, 1, 1, 1, 1, 1, 1, 4, 0, /* 0x2x */
+ 1, 1, 1, 1, 1, 1, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, /* 0x3x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */
+ 0, 0, 0, 0, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */
+ 3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xax */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xbx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */
+ 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3 }; /* 0xfx */
+
+int lock_legal_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* 0xax */
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, /* 0xbx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 0xfx */
+
+/* (modrm >> 3) & 0x07 */
+int lock_legal_ba[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
+
+/* Also applies to 81, 82, and 83 */
+int lock_legal_80[8] = { 1, 1, 1, 1, 1, 1, 1, 0 };
+
+/* Also applies to F7 */
+int lock_legal_f6[8] = { 0, 0, 1, 1, 0, 0, 0, 0 };
+
+/* Also applies to FF */
+int lock_legal_fe[8] = { 1, 1, 0, 0, 0, 0, 0, 0 };
+
uint32_t addr64;
uint32_t addr64_2;
uint32_t addr64a[8];
@@ -128,9 +178,9 @@ uint32_t addr64a_2[8];
static pc_timer_t *cpu_fast_off_timer = NULL;
static double cpu_fast_off_period = 0.0;
-#define AMD_SYSCALL_EIP (msr.star & 0xFFFFFFFF)
-#define AMD_SYSCALL_SB ((msr.star >> 32) & 0xFFFF)
-#define AMD_SYSRET_SB ((msr.star >> 48) & 0xFFFF)
+#define AMD_SYSCALL_EIP (msr.amd_star & 0xFFFFFFFF)
+#define AMD_SYSCALL_SB ((msr.amd_star >> 32) & 0xFFFF)
+#define AMD_SYSRET_SB ((msr.amd_star >> 48) & 0xFFFF)
/* These #define's and enum have been borrowed from Bochs. */
/* SMM feature masks */
@@ -376,6 +426,52 @@ x386_common_log(const char *fmt, ...)
# define x386_common_log(fmt, ...)
#endif
+int
+is_lock_legal(uint32_t fetchdat)
+{
+ int legal = 1;
+
+ if (is386) {
+ fetch_dat_t fetch_dat;
+ fetch_dat.fd = fetchdat;
+
+ legal = lock_legal[fetch_dat.b[0]];
+ if (legal == 1)
+ legal = 1; // ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
+ else if (legal == 2) {
+ legal = lock_legal_0f[fetch_dat.b[1]];
+ if (legal == 1)
+ legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,reg is illegal */
+ else if (legal == 3) {
+ legal = lock_legal_ba[(fetch_dat.b[2] >> 3) & 0x07];
+ if (legal == 1)
+ legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,imm is illegal */
+ }
+ } else if (legal == 3) switch(fetch_dat.b[0]) {
+ case 0x80 ... 0x83:
+ legal = lock_legal_80[(fetch_dat.b[1] >> 3) & 0x07];
+ if (legal == 1)
+ legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
+ break;
+ case 0xf6 ... 0xf7:
+ legal = lock_legal_f6[(fetch_dat.b[1] >> 3) & 0x07];
+ if (legal == 1)
+ legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
+ break;
+ case 0xfe ... 0xff:
+ legal = lock_legal_fe[(fetch_dat.b[1] >> 3) & 0x07];
+ if (legal == 1)
+ legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
+ break;
+ default:
+ legal = 0;
+ break;
+ }
+ }
+
+ return legal;
+}
+
/*Prefetch emulation is a fairly simplistic model:
- All instruction bytes must be fetched before it starts.
- Cycles used for non-instruction memory accesses are counted and subtracted
@@ -1412,7 +1508,7 @@ x86_int(int num)
cpu_state.pc = cpu_state.oldpc;
if (msw & 1)
- is486 ? pmodeint(num, 0) : pmodeint_2386(num, 0);
+ cpu_use_exec ? pmodeint(num, 0) : pmodeint_2386(num, 0);
else {
addr = (num << 2) + idt.base;
@@ -1445,7 +1541,7 @@ x86_int(int num)
oxpc = cpu_state.pc;
#endif
cpu_state.pc = readmemw(0, addr);
- is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
+ cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
}
}
@@ -1462,7 +1558,7 @@ x86_int_sw(int num)
cycles -= timing_int;
if (msw & 1)
- is486 ? pmodeint(num, 1) : pmodeint_2386(num, 1);
+ cpu_use_exec ? pmodeint(num, 1) : pmodeint_2386(num, 1);
else {
addr = (num << 2) + idt.base;
@@ -1487,12 +1583,15 @@ x86_int_sw(int num)
oxpc = cpu_state.pc;
#endif
cpu_state.pc = readmemw(0, addr);
- is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
+ cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
cycles -= timing_int_rm;
}
}
- trap &= ~1;
+ if (cpu_use_exec)
+ trap = 0;
+ else
+ trap &= ~1;
CPU_BLOCK_END();
}
@@ -1529,13 +1628,16 @@ x86_int_sw_rm(int num)
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = new_pc;
- is486 ? loadcs(new_cs) : loadcs_2386(new_cs);
+ cpu_use_exec ? loadcs(new_cs) : loadcs_2386(new_cs);
#ifndef USE_NEW_DYNAREC
oxpc = cpu_state.pc;
#endif
cycles -= timing_int_rm;
- trap &= ~1;
+ if (cpu_use_exec)
+ trap = 0;
+ else
+ trap &= ~1;
CPU_BLOCK_END();
return 0;
@@ -1552,6 +1654,13 @@ checkio(uint32_t port, int mask)
{
uint32_t t;
+ if (!(tr.access & 0x08)) {
+ if ((CPL) > (IOPL))
+ return 1;
+
+ return 0;
+ }
+
cpl_override = 1;
t = readmemw(tr.base, 0x66);
diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h
index 35d4f7cc86..6ef65771d4 100644
--- a/src/cpu/386_common.h
+++ b/src/cpu/386_common.h
@@ -49,6 +49,82 @@
# define do_mmut_wb(s, a, b) do_mmutranslate_2386((s) + (a), b, 1, 1)
# define do_mmut_ww(s, a, b) do_mmutranslate_2386((s) + (a), b, 2, 1)
# define do_mmut_wl(s, a, b) do_mmutranslate_2386((s) + (a), b, 4, 1)
+#elif defined(USE_DEBUG_REGS_486)
+# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
+# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
+# define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
+# define readmemb(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) ? readmembl((s) + (a)) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
+# define readmemw(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 1)) ? readmemwl((s) + (a)) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
+# define readmeml(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 3)) ? readmemll((s) + (a)) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
+# define readmemq(s, a) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF) || (((s) + (a)) & 7)) ? readmemql((s) + (a)) : *(uint64_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
+
+# define writememb_n(s, a, b, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \
+ writemembl_no_mmut((s) + (a), b, v); \
+ else \
+ *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+# define writememw_n(s, a, b, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \
+ writememwl_no_mmut((s) + (a), b, v); \
+ else \
+ *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+# define writememl_n(s, a, b, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \
+ writememll_no_mmut((s) + (a), b, v); \
+ else \
+ *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+# define writememb(s, a, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \
+ writemembl((s) + (a), v); \
+ else \
+ *(uint8_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+# define writememw(s, a, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \
+ writememwl((s) + (a), v); \
+ else \
+ *(uint16_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+# define writememl(s, a, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \
+ writememll((s) + (a), v); \
+ else \
+ *(uint32_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+# define writememq(s, a, v) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 7) || (dr[7] & 0xFF)) \
+ writememql((s) + (a), v); \
+ else \
+ *(uint64_t *) (writelookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))) = v
+
+# define do_mmut_rb(s, a, b) \
+ if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 1, 0)
+# define do_mmut_rw(s, a, b) \
+ if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 2, 0)
+# define do_mmut_rl(s, a, b) \
+ if (readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 4, 0)
+# define do_mmut_rb2(s, a, b) \
+ old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \
+ if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 1, 0)
+# define do_mmut_rw2(s, a, b) \
+ old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \
+ if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 2, 0)
+# define do_mmut_rl2(s, a, b) \
+ old_rl2 = readlookup2[(uint32_t) ((s) + (a)) >> 12]; \
+ if (old_rl2 == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 4, 0)
+
+# define do_mmut_wb(s, a, b) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 1, 1)
+# define do_mmut_ww(s, a, b) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1) || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 2, 1)
+# define do_mmut_wl(s, a, b) \
+ if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3) || (dr[7] & 0xFF)) \
+ do_mmutranslate((s) + (a), b, 4, 1)
#else
# define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
# define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
@@ -225,19 +301,37 @@ int checkio(uint32_t port, int mask);
static __inline uint8_t
fastreadb(uint32_t a)
{
- return readmembl_2386(a);
+ uint8_t ret;
+ read_type = 1;
+ ret = readmembl_2386(a);
+ read_type = 4;
+ if (cpu_state.abrt)
+ return 0;
+ return ret;
}
static __inline uint16_t
fastreadw(uint32_t a)
{
- return readmemwl_2386(a);
+ uint16_t ret;
+ read_type = 1;
+ ret = readmemwl_2386(a);
+ read_type = 4;
+ if (cpu_state.abrt)
+ return 0;
+ return ret;
}
static __inline uint32_t
fastreadl(uint32_t a)
{
- return readmemll_2386(a);
+ uint32_t ret;
+ read_type = 1;
+ ret = readmemll_2386(a);
+ read_type = 4;
+ if (cpu_state.abrt)
+ return 0;
+ return ret;
}
#else
static __inline uint8_t
@@ -245,6 +339,11 @@ fastreadb(uint32_t a)
{
uint8_t *t;
+# ifdef USE_DEBUG_REGS_486
+ read_type = 1;
+ mem_debug_check_addr(a, read_type);
+ read_type = 4;
+# endif
if ((a >> 12) == pccache)
# if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
return *((uint8_t *) (((uintptr_t) &pccache2[a] & 0x00000000ffffffffULL) | ((uintptr_t) &pccache2[0] & 0xffffffff00000000ULL)));
@@ -268,6 +367,12 @@ fastreadw(uint32_t a)
{
uint8_t *t;
uint16_t val;
+# ifdef USE_DEBUG_REGS_486
+ read_type = 1;
+ mem_debug_check_addr(a, read_type);
+ mem_debug_check_addr(a + 1, read_type);
+ read_type = 4;
+# endif
if ((a & 0xFFF) > 0xFFE) {
val = fastreadb(a);
val |= (fastreadb(a + 1) << 8);
@@ -297,6 +402,14 @@ fastreadl(uint32_t a)
{
uint8_t *t;
uint32_t val;
+# ifdef USE_DEBUG_REGS_486
+ int i;
+ read_type = 1;
+ for (i = 0; i < 4; i++) {
+ mem_debug_check_addr(a + i, read_type);
+ }
+ read_type = 4;
+# endif
if ((a & 0xFFF) < 0xFFD) {
if ((a >> 12) != pccache) {
t = getpccache(a);
@@ -342,31 +455,41 @@ extern int opcode_length[256];
static __inline uint16_t
fastreadw_fetch(uint32_t a)
{
- uint16_t val;
+ uint16_t ret;
if ((a & 0xFFF) > 0xFFE) {
- val = fastreadb(a);
- if (opcode_length[val & 0xff] > 1)
- val |= ((uint16_t) fastreadb(a + 1) << 8);
- return val;
+ ret = fastreadb(a);
+ if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 1))
+ ret |= ((uint16_t) fastreadb(a + 1) << 8);
+ } else if (cpu_state.abrt)
+ ret = 0;
+ else {
+ read_type = 1;
+ ret = readmemwl_2386(a);
+ read_type = 4;
}
- return readmemwl_2386(a);
+ return ret;
}
static __inline uint32_t
fastreadl_fetch(uint32_t a)
{
- uint32_t val;
+ uint32_t ret;
if (cpu_16bitbus || ((a & 0xFFF) > 0xFFC)) {
- val = fastreadw_fetch(a);
- if (opcode_length[val & 0xff] > 2)
- val |= ((uint32_t) fastreadw(a + 2) << 16);
- return val;
+ ret = fastreadw_fetch(a);
+ if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 2))
+ ret |= ((uint32_t) fastreadw(a + 2) << 16);
+ } else if (cpu_state.abrt)
+ ret = 0;
+ else {
+ read_type = 1;
+ ret = readmemll_2386(a);
+ read_type = 4;
}
- return readmemll_2386(a);
+ return ret;
}
#else
static __inline uint16_t
@@ -374,6 +497,12 @@ fastreadw_fetch(uint32_t a)
{
uint8_t *t;
uint16_t val;
+# ifdef USE_DEBUG_REGS_486
+ read_type = 1;
+ mem_debug_check_addr(a, read_type);
+ mem_debug_check_addr(a + 1, read_type);
+ read_type = 4;
+# endif
if ((a & 0xFFF) > 0xFFE) {
val = fastreadb(a);
if (opcode_length[val & 0xff] > 1)
@@ -404,6 +533,14 @@ fastreadl_fetch(uint32_t a)
{
uint8_t *t;
uint32_t val;
+# ifdef USE_DEBUG_REGS_486
+ int i;
+ read_type = 1;
+ for (i = 0; i < 4; i++) {
+ mem_debug_check_addr(a + i, read_type);
+ }
+ read_type = 4;
+# endif
if ((a & 0xFFF) < 0xFFD) {
if ((a >> 12) != pccache) {
t = getpccache(a);
diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c
index c96e3420d4..d8a33a6240 100644
--- a/src/cpu/386_dynarec.c
+++ b/src/cpu/386_dynarec.c
@@ -19,6 +19,7 @@
#include "x86_ops.h"
#include "x86seg_common.h"
#include "x86seg.h"
+#include "x87_sf.h"
#include "x87.h"
#include <86box/io.h>
#include <86box/mem.h>
@@ -28,6 +29,7 @@
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/machine.h>
+#include <86box/plat_fallthrough.h>
#include <86box/gdbstub.h>
#ifdef USE_DYNAREC
# include "codegen.h"
@@ -224,7 +226,11 @@ fetch_ea_16_long(uint32_t rmdat)
#include "386_ops.h"
-#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
+#ifdef USE_DEBUG_REGS_486
+# define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG) && !(dr[7] & 0xFF))
+#else
+# define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
+#endif
#ifdef USE_DYNAREC
int32_t cycles_main = 0;
@@ -269,7 +275,11 @@ exec386_dynarec_int(void)
cpu_block_end = 0;
x86_was_reset = 0;
+# ifdef USE_DEBUG_REGS_486
+ if (trap & 2) {
+# else
if (trap == 2) {
+# endif
/* Handle the T bit in the new TSS first. */
CPU_BLOCK_END();
goto block_ended;
@@ -286,6 +296,13 @@ exec386_dynarec_int(void)
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
+# ifdef USE_DEBUG_REGS_486
+ if (UNLIKELY(cpu_386_check_instruction_fault())) {
+ x86gen();
+ goto block_ended;
+ }
+# endif
+
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
# ifdef ENABLE_386_DYNAREC_LOG
if (in_smm)
@@ -296,9 +313,16 @@ exec386_dynarec_int(void)
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
+# ifdef USE_DEBUG_REGS_486
+ trap |= !!(cpu_state.flags & T_FLAG);
+# else
trap = cpu_state.flags & T_FLAG;
+# endif
cpu_state.pc++;
+# ifdef USE_DEBUG_REGS_486
+ cpu_state.eflags &= ~(RF_FLAG);
+# endif
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
}
@@ -307,6 +331,16 @@ exec386_dynarec_int(void)
cpu_state.pc &= 0xffff;
# endif
+# ifdef USE_DEBUG_REGS_486
+ if (!cpu_state.abrt) {
+ if (!rf_flag_no_clear) {
+ cpu_state.eflags &= ~RF_FLAG;
+ }
+
+ rf_flag_no_clear = 0;
+ }
+# endif
+
if (((cs + cpu_state.pc) >> 12) != pccache)
CPU_BLOCK_END();
@@ -316,6 +350,9 @@ exec386_dynarec_int(void)
CPU_BLOCK_END();
}
+ if (cpu_init)
+ CPU_BLOCK_END();
+
if (cpu_state.abrt)
CPU_BLOCK_END();
if (smi_line)
@@ -330,7 +367,14 @@ exec386_dynarec_int(void)
block_ended:
if (!cpu_state.abrt && trap) {
+# ifdef USE_DEBUG_REGS_486
+ //pclog("Debug trap 0x%X\n", trap);
+ if (trap & 2) dr[6] |= 0x8000;
+ if (trap & 1) dr[6] |= 0x4000;
+# else
dr[6] |= (trap == 2) ? 0x8000 : 0x4000;
+# endif
+
trap = 0;
# ifndef USE_NEW_DYNAREC
oldcs = CS;
@@ -373,7 +417,8 @@ exec386_dynarec_dyn(void)
int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
uint64_t byte_mask = 1ULL << (PAGE_BYTE_MASK_MASK & 0x3f);
- if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask))
+ if ((page->code_present_mask & mask) ||
+ ((page->mem != page_ff) && (page->byte_code_present_mask[byte_offset] & byte_mask)))
# else
if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
# endif
@@ -550,6 +595,9 @@ exec386_dynarec_dyn(void)
# endif
CPU_BLOCK_END();
+ if (cpu_init)
+ CPU_BLOCK_END();
+
if ((cpu_state.flags & T_FLAG) || (trap == 2))
CPU_BLOCK_END();
if (smi_line)
@@ -647,6 +695,9 @@ exec386_dynarec_dyn(void)
# endif
CPU_BLOCK_END();
+ if (cpu_init)
+ CPU_BLOCK_END();
+
if (cpu_state.flags & T_FLAG)
CPU_BLOCK_END();
if (smi_line)
@@ -726,6 +777,11 @@ exec386_dynarec(int32_t cycs)
exec386_dynarec_dyn();
}
+ if (cpu_init) {
+ cpu_init = 0;
+ resetx86();
+ }
+
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
@@ -842,6 +898,13 @@ exec386(int32_t cycs)
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
+#ifdef USE_DEBUG_REGS_486
+ if (UNLIKELY(cpu_386_check_instruction_fault())) {
+ x86gen();
+ goto block_ended;
+ }
+#endif
+
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
if (!cpu_state.abrt) {
@@ -851,9 +914,16 @@ exec386(int32_t cycs)
#endif
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
+#ifdef USE_DEBUG_REGS_486
+ trap |= !!(cpu_state.flags & T_FLAG);
+#else
trap = cpu_state.flags & T_FLAG;
+#endif
cpu_state.pc++;
+#ifdef USE_DEBUG_REGS_486
+ cpu_state.eflags &= ~(RF_FLAG);
+#endif
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
@@ -871,6 +941,9 @@ exec386(int32_t cycs)
if (cpu_end_block_after_ins)
cpu_end_block_after_ins--;
+#ifdef USE_DEBUG_REGS_486
+block_ended:
+#endif
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
@@ -895,12 +968,21 @@ exec386(int32_t cycs)
}
} else if (trap) {
flags_rebuild();
+#ifdef USE_DEBUG_REGS_486
+ if (trap & 1)
+ dr[6] |= 0x4000;
+ if (trap & 2)
+ dr[6] |= 0x8000;
+#endif
+
trap = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
+#ifndef USE_DEBUG_REGS_486
dr[6] |= 0x4000;
+#endif
x86_int(1);
}
diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c
index 77b72ef599..c31b725b23 100644
--- a/src/cpu/386_dynarec_ops.c
+++ b/src/cpu/386_dynarec_ops.c
@@ -15,6 +15,7 @@
#include "x86_ops.h"
#include "x86seg_common.h"
#include "x86seg.h"
+#include "x87_sf.h"
#include "x87.h"
#include "x86_flags.h"
#include <86box/io.h>
@@ -24,6 +25,7 @@
#include <86box/gdbstub.h>
#include "codegen.h"
#include <86box/plat_unused.h>
+#include <86box/plat_fallthrough.h>
#define CPU_BLOCK_END() cpu_block_end = 1
diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h
index 710031ef1e..3e0d191f20 100644
--- a/src/cpu/386_ops.h
+++ b/src/cpu/386_ops.h
@@ -186,7 +186,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
#else
# include "x86_ops_flag.h"
#endif
-#include "x86_ops_fpu.h"
+#ifdef OPS_286_386
+# include "x86_ops_fpu_2386.h"
+#else
+# include "x86_ops_fpu.h"
+#endif
#include "x86_ops_inc_dec.h"
#include "x86_ops_int.h"
#include "x86_ops_io.h"
@@ -216,7 +220,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
#endif
#include "x86_ops_mul.h"
#include "x86_ops_pmode.h"
-#include "x86_ops_prefix.h"
+#ifdef OPS_286_386
+# include "x86_ops_prefix_2386.h"
+#else
+# include "x86_ops_prefix.h"
+#endif
#ifdef IS_DYNAREC
# include "x86_ops_rep_dyn.h"
#else
@@ -641,7 +649,7 @@ const OpFn OP_TABLE(386_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
-/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -656,14 +664,14 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
-/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*32-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
-/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -678,14 +686,14 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
-/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*16-bit data, 32-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
-/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -700,14 +708,14 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
-/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*32-bit data, 32-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
-/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -722,7 +730,7 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
-/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
diff --git a/src/cpu/808x.c b/src/cpu/808x.c
index 0b6bd66b50..6705563c0b 100644
--- a/src/cpu/808x.c
+++ b/src/cpu/808x.c
@@ -56,7 +56,6 @@ static uint32_t *opseg[4];
static x86seg *_opseg[4];
static int noint = 0;
-static int in_lock = 0;
static int cpu_alu_op, pfq_size;
static uint32_t cpu_src = 0, cpu_dest = 0;
@@ -545,7 +544,6 @@ reset_808x(int hard)
{
biu_cycles = 0;
in_rep = 0;
- in_lock = 0;
completed = 1;
repeating = 0;
clear_lock = 0;
@@ -787,6 +785,7 @@ seteaq(uint64_t val)
complicates compiling. */
#define FPU_8087
#define tempc tempc_fpu
+#include "x87_sf.h"
#include "x87.h"
#include "x87_ops.h"
#undef tempc
@@ -1223,34 +1222,48 @@ static void
add(int bits)
{
int size_mask = (1 << bits) - 1;
+ int special_case = 0;
+ uint32_t temp_src = cpu_src;
+
+ if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
+ special_case = 1;
cpu_data = cpu_dest + cpu_src;
+ if ((cpu_alu_op == 2) && (cpu_state.flags & C_FLAG))
+ cpu_src--;
set_apzs(bits);
set_of_add(bits);
/* Anything - FF with carry on is basically anything + 0x100: value stays
unchanged but carry goes on. */
- if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
+ if (special_case)
cpu_state.flags |= C_FLAG;
else
- set_cf((cpu_src & size_mask) > (cpu_data & size_mask));
+ set_cf((temp_src & size_mask) > (cpu_data & size_mask));
}
static void
sub(int bits)
{
int size_mask = (1 << bits) - 1;
+ int special_case = 0;
+ uint32_t temp_src = cpu_src;
+
+ if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
+ special_case = 1;
cpu_data = cpu_dest - cpu_src;
+ if ((cpu_alu_op == 3) && (cpu_state.flags & C_FLAG))
+ cpu_src--;
set_apzs(bits);
set_of_sub(bits);
/* Anything - FF with carry on is basically anything - 0x100: value stays
unchanged but carry goes on. */
- if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
+ if (special_case)
cpu_state.flags |= C_FLAG;
else
- set_cf((cpu_src & size_mask) > (cpu_dest & size_mask));
+ set_cf((temp_src & size_mask) > (cpu_dest & size_mask));
}
static void
@@ -3184,31 +3197,66 @@ execx86(int cycs)
if (!hasfpu)
geteaw();
else
- switch (opcode) {
- case 0xD8:
- ops_fpu_8087_d8[(rmdat >> 3) & 0x1f]((uint32_t) rmdat);
- break;
- case 0xD9:
- ops_fpu_8087_d9[rmdat & 0xff]((uint32_t) rmdat);
- break;
- case 0xDA:
- ops_fpu_8087_da[rmdat & 0xff]((uint32_t) rmdat);
- break;
- case 0xDB:
- ops_fpu_8087_db[rmdat & 0xff]((uint32_t) rmdat);
- break;
- case 0xDC:
- ops_fpu_8087_dc[(rmdat >> 3) & 0x1f]((uint32_t) rmdat);
- break;
- case 0xDD:
- ops_fpu_8087_dd[rmdat & 0xff]((uint32_t) rmdat);
- break;
- case 0xDE:
- ops_fpu_8087_de[rmdat & 0xff]((uint32_t) rmdat);
- break;
- case 0xDF:
- ops_fpu_8087_df[rmdat & 0xff]((uint32_t) rmdat);
- break;
+ if (fpu_softfloat) {
+ switch (opcode) {
+ case 0xD8:
+ ops_sf_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat);
+ break;
+ case 0xD9:
+ ops_sf_fpu_8087_d9[rmdat & 0xff](rmdat);
+ break;
+ case 0xDA:
+ ops_sf_fpu_8087_da[rmdat & 0xff](rmdat);
+ break;
+ case 0xDB:
+ ops_sf_fpu_8087_db[rmdat & 0xff](rmdat);
+ break;
+ case 0xDC:
+ ops_sf_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat);
+ break;
+ case 0xDD:
+ ops_sf_fpu_8087_dd[rmdat & 0xff](rmdat);
+ break;
+ case 0xDE:
+ ops_sf_fpu_8087_de[rmdat & 0xff](rmdat);
+ break;
+ case 0xDF:
+ ops_sf_fpu_8087_df[rmdat & 0xff](rmdat);
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ switch (opcode) {
+ case 0xD8:
+ ops_fpu_8087_d8[(rmdat >> 3) & 0x1f](rmdat);
+ break;
+ case 0xD9:
+ ops_fpu_8087_d9[rmdat & 0xff](rmdat);
+ break;
+ case 0xDA:
+ ops_fpu_8087_da[rmdat & 0xff](rmdat);
+ break;
+ case 0xDB:
+ ops_fpu_8087_db[rmdat & 0xff](rmdat);
+ break;
+ case 0xDC:
+ ops_fpu_8087_dc[(rmdat >> 3) & 0x1f](rmdat);
+ break;
+ case 0xDD:
+ ops_fpu_8087_dd[rmdat & 0xff](rmdat);
+ break;
+ case 0xDE:
+ ops_fpu_8087_de[rmdat & 0xff](rmdat);
+ break;
+ case 0xDF:
+ ops_fpu_8087_df[rmdat & 0xff](rmdat);
+ break;
+
+ default:
+ break;
+ }
}
cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on
the 286+ core, but not here. */
diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt
index bd03a5558f..a3677767d4 100644
--- a/src/cpu/CMakeLists.txt
+++ b/src/cpu/CMakeLists.txt
@@ -23,16 +23,19 @@ endif()
if(CYRIX_6X86)
target_compile_definitions(cpu PRIVATE USE_CYRIX_6X86)
+
+ add_library(ct686 OBJECT codegen_timing_686.c)
+ target_link_libraries(86Box ct686)
endif()
if(DYNAREC)
target_sources(cpu PRIVATE 386_dynarec_ops.c)
- add_library(cgt OBJECT codegen_timing_486.c codegen_timing_686.c
+ add_library(cgt OBJECT codegen_timing_486.c
codegen_timing_common.c codegen_timing_k6.c
codegen_timing_pentium.c codegen_timing_p6.c
codegen_timing_winchip.c codegen_timing_winchip2.c)
endif()
-add_subdirectory(softfloat)
-target_link_libraries(86Box softfloat)
+add_subdirectory(softfloat3e)
+target_link_libraries(86Box softfloat3e)
diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c
index e862b123e7..548a9ec285 100644
--- a/src/cpu/codegen_timing_486.c
+++ b/src/cpu/codegen_timing_486.c
@@ -9,6 +9,7 @@
#include "x86.h"
#include "x86_ops.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ops.h"
diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c
index a6800c5b22..6ea5ac543c 100644
--- a/src/cpu/codegen_timing_686.c
+++ b/src/cpu/codegen_timing_686.c
@@ -19,6 +19,7 @@
#include "x86.h"
#include "x86_ops.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_timing_common.h"
diff --git a/src/cpu/codegen_timing_k6.c b/src/cpu/codegen_timing_k6.c
index 4a9f23cd82..6a28718840 100644
--- a/src/cpu/codegen_timing_k6.c
+++ b/src/cpu/codegen_timing_k6.c
@@ -12,6 +12,7 @@
#include "x86.h"
#include "x86_ops.h"
#include "x86seg_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include "386_common.h"
#include "codegen.h"
diff --git a/src/cpu/codegen_timing_p6.c b/src/cpu/codegen_timing_p6.c
index 2c087ae86c..25c098ca40 100644
--- a/src/cpu/codegen_timing_p6.c
+++ b/src/cpu/codegen_timing_p6.c
@@ -13,6 +13,7 @@
#include "x86.h"
#include "x86_ops.h"
#include "x86seg_common.h"
+#include "x87_sf.h"
#include "x87.h"
#include "386_common.h"
#include "codegen.h"
diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c
index 3951acc942..af344307f7 100644
--- a/src/cpu/codegen_timing_pentium.c
+++ b/src/cpu/codegen_timing_pentium.c
@@ -21,6 +21,7 @@
#include "x86.h"
#include "x86_ops.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ops.h"
diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c
index 11dd912b4f..76ea8b9548 100644
--- a/src/cpu/codegen_timing_winchip.c
+++ b/src/cpu/codegen_timing_winchip.c
@@ -9,6 +9,7 @@
#include "x86.h"
#include "x86_ops.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ops.h"
diff --git a/src/cpu/codegen_timing_winchip2.c b/src/cpu/codegen_timing_winchip2.c
index d4e32611e4..ea206f068e 100644
--- a/src/cpu/codegen_timing_winchip2.c
+++ b/src/cpu/codegen_timing_winchip2.c
@@ -18,6 +18,7 @@
#include "x86.h"
#include "x86_ops.h"
+#include "x87_sf.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ops.h"
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index e05ec0d9c3..20476eec9e 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -29,6 +29,8 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
+#include "x86.h"
+#include "x87_sf.h"
#include <86box/device.h>
#include <86box/machine.h>
#include <86box/io.h>
@@ -55,27 +57,37 @@
#define CCR3_NMI_EN (1 << 1)
enum {
- CPUID_FPU = (1 << 0),
- CPUID_VME = (1 << 1),
- CPUID_PSE = (1 << 3),
- CPUID_TSC = (1 << 4),
- CPUID_MSR = (1 << 5),
- CPUID_PAE = (1 << 6),
- CPUID_MCE = (1 << 7),
- CPUID_CMPXCHG8B = (1 << 8),
- CPUID_AMDSEP = (1 << 10),
- CPUID_SEP = (1 << 11),
- CPUID_MTRR = (1 << 12),
- CPUID_PGE = (1 << 13),
- CPUID_MCA = (1 << 14),
- CPUID_CMOV = (1 << 15),
- CPUID_MMX = (1 << 23),
- CPUID_FXSR = (1 << 24)
+ CPUID_FPU = (1 << 0), /* On-chip Floating Point Unit */
+ CPUID_VME = (1 << 1), /* Virtual 8086 mode extensions */
+ CPUID_DE = (1 << 2), /* Debugging extensions */
+ CPUID_PSE = (1 << 3), /* Page Size Extension */
+ CPUID_TSC = (1 << 4), /* Time Stamp Counter */
+ CPUID_MSR = (1 << 5), /* Model-specific registers */
+ CPUID_PAE = (1 << 6), /* Physical Address Extension */
+ CPUID_MCE = (1 << 7), /* Machine Check Exception */
+ CPUID_CMPXCHG8B = (1 << 8), /* CMPXCHG8B instruction */
+ CPUID_APIC = (1 << 9), /* On-chip APIC */
+ CPUID_AMDPGE = (1 << 9), /* Global Page Enable (AMD K5 Model 0 only) */
+ CPUID_AMDSEP = (1 << 10), /* SYSCALL and SYSRET instructions (AMD K6 only) */
+ CPUID_SEP = (1 << 11), /* SYSENTER and SYSEXIT instructions (SYSCALL and SYSRET if EAX=80000001h) */
+ CPUID_MTRR = (1 << 12), /* Memory type range registers */
+ CPUID_PGE = (1 << 13), /* Page Global Enable */
+ CPUID_MCA = (1 << 14), /* Machine Check Architecture */
+ CPUID_CMOV = (1 << 15), /* Conditional move instructions */
+ CPUID_PAT = (1 << 16), /* Page Attribute Table */
+ CPUID_MMX = (1 << 23), /* MMX technology */
+ CPUID_FXSR = (1 << 24) /* FXSAVE and FXRSTOR instructions */
};
-/*Addition flags returned by CPUID function 0x80000001*/
-#define CPUID_3DNOW (1UL << 31UL)
-#define CPUID_3DNOWE (1UL << 30UL)
+/* Additional flags returned by CPUID function 0x80000001 */
+#define CPUID_3DNOWE (1UL << 30UL) /* Extended 3DNow! instructions */
+#define CPUID_3DNOW (1UL << 31UL) /* 3DNow! instructions */
+
+/* Remove the Debugging Extensions CPUID flag if not compiled
+ with debug register support for 486 and later CPUs. */
+#ifndef USE_DEBUG_REGS_486
+# define CPUID_DE 0
+#endif
/* Make sure this is as low as possible. */
cpu_state_t cpu_state;
@@ -183,6 +195,7 @@ int cpu_64bitbus;
int cpu_cyrix_alignment;
int cpu_cpurst_on_sr;
int cpu_use_exec = 0;
+int cpu_override_interpreter;
int CPUID;
int is186;
@@ -244,8 +257,7 @@ uint32_t cache_index = 0;
uint8_t _cache[2048];
uint64_t cpu_CR4_mask;
-uint64_t tsc = 0;
-uint64_t pmc[2] = { 0, 0 };
+uint64_t tsc = 0;
double cpu_dmulti;
double cpu_busspeed;
@@ -493,7 +505,8 @@ cpu_set(void)
acycs = 0;
#endif
- soft_reset_pci = 0;
+ soft_reset_pci = 0;
+ cpu_init = 0;
cpu_alt_reset = 0;
unmask_a20_in_smm = 0;
@@ -1605,11 +1618,16 @@ cpu_set(void)
cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE);
if (cpu_s->cpu_type <= CPU_K6)
cpu_CR4_mask |= CR4_PCE;
- }
+ else if (cpu_s->cpu_type >= CPU_K6_2C)
+ cpu_CR4_mask |= CR4_PGE;
+ } else
+ cpu_CR4_mask |= CR4_PGE;
#else
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE;
if (cpu_s->cpu_type == CPU_K6)
cpu_CR4_mask |= CR4_PCE;
+ else if (cpu_s->cpu_type >= CPU_K6_2C)
+ cpu_CR4_mask |= CR4_PGE;
#endif
#ifdef USE_DYNAREC
@@ -1795,7 +1813,8 @@ cpu_set(void)
} else
#endif
/* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */
- if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC)) {
+ if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL) ||
+ cpu_iscyrix || (cpu_s->cpu_type > CPU_486DLC) || cpu_override_interpreter) {
cpu_exec = exec386;
cpu_use_exec = 1;
} else
@@ -1906,7 +1925,7 @@ cpu_CPUID(void)
case CPU_i486SX_SLENH:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -1920,7 +1939,7 @@ cpu_CPUID(void)
case CPU_i486DX_SLENH:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
@@ -1936,21 +1955,21 @@ cpu_CPUID(void)
case CPU_ENH_Am486DX:
if (!EAX) {
- EAX = 1;
- EBX = 0x68747541;
+ EAX = 0x00000001;
+ EBX = 0x68747541;/* AuthenticAMD */
ECX = 0x444D4163;
EDX = 0x69746E65;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU; /*FPU*/
+ EDX = CPUID_FPU;
} else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_WINCHIP:
if (!EAX) {
- EAX = 1;
+ EAX = 0x00000001;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
@@ -1961,9 +1980,9 @@ cpu_CPUID(void)
EDX = 0x48727561;
}
} else if (EAX == 1) {
- EAX = 0x540;
+ EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID);
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
@@ -1975,7 +1994,7 @@ cpu_CPUID(void)
case CPU_WINCHIP2:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
@@ -1987,9 +2006,9 @@ cpu_CPUID(void)
}
break;
case 1:
- EAX = CPUID;
+ EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID);
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
@@ -2000,7 +2019,7 @@ cpu_CPUID(void)
break;
case 0x80000001:
EAX = CPUID;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
@@ -2032,13 +2051,15 @@ cpu_CPUID(void)
case CPU_PENTIUM:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
+ if (cpu_s->cpu_type != CPU_P24T)
+ EDX |= CPUID_MCE;
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2047,103 +2068,123 @@ cpu_CPUID(void)
case CPU_K5:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x68747541;
+ EBX = 0x68747541; /* AuthenticAMD */
EDX = 0x69746E65;
ECX = 0x444D4163;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE;
} else
EAX = EBX = ECX = EDX = 0;
break;
case CPU_5K86:
- if (!EAX) {
- EAX = 0x00000001;
- EBX = 0x68747541;
- EDX = 0x69746E65;
- ECX = 0x444D4163;
- } else if (EAX == 1) {
- EAX = CPUID;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
- } else if (EAX == 0x80000000) {
- EAX = 0x80000005;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000001) {
- EAX = CPUID;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B;
- } else if (EAX == 0x80000002) {
- EAX = 0x2D444D41;
- EBX = 0x7428354B;
- ECX = 0x5020296D;
- EDX = 0x65636F72;
- } else if (EAX == 0x80000003) {
- EAX = 0x726F7373;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000004)
- EAX = EBX = ECX = EDX = 0;
- else if (EAX == 0x80000005) {
- EAX = 0;
- EBX = 0x04800000;
- ECX = 0x08040120;
- EDX = 0x10040120;
- } else
- EAX = EBX = ECX = EDX = 0;
+ switch (EAX) {
+ case 0:
+ EAX = 0x00000001;
+ EBX = 0x68747541; /* AuthenticAMD */
+ EDX = 0x69746E65;
+ ECX = 0x444D4163;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000001:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
+ break;
+ case 0x80000002: /* Processor name string */
+ EAX = 0x2D444D41; /* AMD-K5(tm) Proce */
+ EBX = 0x7428354B;
+ ECX = 0x5020296D;
+ EDX = 0x65636F72;
+ break;
+ case 0x80000003: /* Processor name string */
+ EAX = 0x726F7373; /* ssor */
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000005: /* Cache information */
+ EAX = 0;
+ EBX = 0x04800000; /* TLBs */
+ ECX = 0x08040120; /* L1 data cache */
+ EDX = 0x10040120; /* L1 instruction cache */
+ break;
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
break;
#endif
case CPU_K6:
- if (!EAX) {
- EAX = 0x00000001;
- EBX = 0x68747541;
- EDX = 0x69746E65;
- ECX = 0x444D4163;
- } else if (EAX == 1) {
- EAX = CPUID;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
- } else if (EAX == 0x80000000) {
- EAX = 0x80000005;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000001) {
- EAX = CPUID + 0x100;
- EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX;
- } else if (EAX == 0x80000002) {
- EAX = 0x2D444D41;
- EBX = 0x6D74364B;
- ECX = 0x202F7720;
- EDX = 0x746C756D;
- } else if (EAX == 0x80000003) {
- EAX = 0x64656D69;
- EBX = 0x65206169;
- ECX = 0x6E657478;
- EDX = 0x6E6F6973;
- } else if (EAX == 0x80000004) {
- EAX = 0x73;
- EBX = ECX = EDX = 0;
- } else if (EAX == 0x80000005) {
- EAX = 0;
- EBX = 0x02800140;
- ECX = 0x20020220;
- EDX = 0x20020220;
- } else if (EAX == 0x8FFFFFFF) {
- EAX = 0x4778654E;
- EBX = 0x72656E65;
- ECX = 0x6F697461;
- EDX = 0x444D416E;
- } else
- EAX = EBX = ECX = EDX = 0;
+ switch (EAX) {
+ case 0:
+ EAX = 0x00000001;
+ EBX = 0x68747541; /* AuthenticAMD */
+ EDX = 0x69746E65;
+ ECX = 0x444D4163;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000001:
+ EAX = CPUID + 0x100;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX;
+ break;
+ case 0x80000002: /* Processor name string */
+ EAX = 0x2D444D41; /* AMD-K6tm w/ mult */
+ EBX = 0x6D74364B;
+ ECX = 0x202F7720;
+ EDX = 0x746C756D;
+ break;
+ case 0x80000003: /* Processor name string */
+ EAX = 0x64656D69; /* imedia extension */
+ EBX = 0x65206169;
+ ECX = 0x6E657478;
+ EDX = 0x6E6F6973;
+ break;
+ case 0x80000004: /* Processor name string */
+ EAX = 0x73; /* s */
+ EBX = ECX = EDX = 0;
+ break;
+ case 0x80000005: /* Cache information */
+ EAX = 0;
+ EBX = 0x02800140; /* TLBs */
+ ECX = 0x20020220; /* L1 data cache */
+ EDX = 0x20020220; /* L1 instruction cache */
+ break;
+ case 0x8FFFFFFF: /* Easter egg */
+ EAX = 0x4778654E; /* NexGenerationAMD */
+ EBX = 0x72656E65;
+ ECX = 0x6F697461;
+ EDX = 0x444D416E;
+ break;
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
break;
case CPU_K6_2:
case CPU_K6_2C:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
EBX = 0x68747541; /* AuthenticAMD */
ECX = 0x444d4163;
EDX = 0x69746e65;
@@ -2151,7 +2192,9 @@ cpu_CPUID(void)
case 1:
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ if (cpu_s->cpu_type == CPU_K6_2C)
+ EDX |= CPUID_PGE;
break;
case 0x80000000:
EAX = 0x80000005;
@@ -2160,7 +2203,9 @@ cpu_CPUID(void)
case 0x80000001:
EAX = CPUID + 0x100;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_3DNOW;
+ if (cpu_s->cpu_type == CPU_K6_2C)
+ EDX |= CPUID_PGE;
break;
case 0x80000002: /* Processor name string */
EAX = 0x2d444d41; /* AMD-K6(tm) 3D pr */
@@ -2174,11 +2219,11 @@ cpu_CPUID(void)
ECX = 0x00000000;
EDX = 0x00000000;
break;
- case 0x80000005: /*Cache information*/
+ case 0x80000005: /* Cache information */
EAX = 0;
- EBX = 0x02800140; /*TLBs*/
- ECX = 0x20020220; /*L1 data cache*/
- EDX = 0x20020220; /*L1 instruction cache*/
+ EBX = 0x02800140; /* TLBs */
+ ECX = 0x20020220; /* L1 data cache */
+ EDX = 0x20020220; /* L1 instruction cache */
break;
default:
EAX = EBX = ECX = EDX = 0;
@@ -2189,7 +2234,7 @@ cpu_CPUID(void)
case CPU_K6_3:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
EBX = 0x68747541; /* AuthenticAMD */
ECX = 0x444d4163;
EDX = 0x69746e65;
@@ -2197,7 +2242,7 @@ cpu_CPUID(void)
case 1:
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000006;
@@ -2206,7 +2251,7 @@ cpu_CPUID(void)
case 0x80000001:
EAX = CPUID + 0x100;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_PGE | CPUID_MMX | CPUID_3DNOW;
break;
case 0x80000002: /* Processor name string */
EAX = 0x2d444d41; /* AMD-K6(tm) 3D+ P */
@@ -2223,8 +2268,8 @@ cpu_CPUID(void)
case 0x80000005: /* Cache information */
EAX = 0;
EBX = 0x02800140; /* TLBs */
- ECX = 0x20020220; /*L1 data cache*/
- EDX = 0x20020220; /*L1 instruction cache*/
+ ECX = 0x20020220; /* L1 data cache */
+ EDX = 0x20020220; /* L1 instruction cache */
break;
case 0x80000006: /* L2 Cache information */
EAX = EBX = EDX = 0;
@@ -2240,7 +2285,7 @@ cpu_CPUID(void)
case CPU_K6_3P:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
EBX = 0x68747541; /* AuthenticAMD */
ECX = 0x444d4163;
EDX = 0x69746e65;
@@ -2248,7 +2293,7 @@ cpu_CPUID(void)
case 1:
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE | CPUID_MMX;
break;
case 0x80000000:
EAX = 0x80000007;
@@ -2257,7 +2302,7 @@ cpu_CPUID(void)
case 0x80000001:
EAX = CPUID + 0x100;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDSEP | CPUID_MMX | CPUID_3DNOW | CPUID_3DNOWE;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_MMX | CPUID_PGE | CPUID_3DNOW | CPUID_3DNOWE;
break;
case 0x80000002: /* Processor name string */
EAX = 0x2d444d41; /* AMD-K6(tm)-III P */
@@ -2297,13 +2342,13 @@ cpu_CPUID(void)
case CPU_PENTIUMMMX:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX;
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2312,7 +2357,7 @@ cpu_CPUID(void)
case CPU_Cx6x86:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
@@ -2326,7 +2371,7 @@ cpu_CPUID(void)
case CPU_Cx6x86L:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
@@ -2340,13 +2385,13 @@ cpu_CPUID(void)
case CPU_CxGX1:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B;
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2354,13 +2399,13 @@ cpu_CPUID(void)
case CPU_Cx6x86MX:
if (!EAX) {
EAX = 0x00000001;
- EBX = 0x69727943;
+ EBX = 0x69727943; /* CyrixInstead */
EDX = 0x736e4978;
ECX = 0x64616574;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX;
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2369,28 +2414,22 @@ cpu_CPUID(void)
case CPU_PENTIUMPRO:
if (!EAX) {
EAX = 0x00000002;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV;
} else if (EAX == 2) {
- /* if (!strcmp(machine_get_internal_name(), "ap61")) {
- EAX = 0x00000001;
- EDX = 0x00000000;
- } else */ {
- EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
- Instruction TLB: 4 MB pages, fully associative, 2 entries
- Data TLB: 4 KB pages, 4-way set associative, 64 entries */
- EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size
- 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size
- Data TLB: 4 MB pages, 4-way set associative, 8 entries
- 1st-level instruction cache:8 KB, 4-way set associative, 32-byte line size */
- }
-
+ EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
+ Instruction TLB: 4 MB pages, fully associative, 2 entries
+ Data TLB: 4 KB pages, 4-way set associative, 64 entries */
EBX = ECX = 0;
+ EDX = 0x06040a42; /* 2nd-level cache: 256 KB, 4-way set associative, 32-byte line size
+ 1st-level data cache: 8 KB, 2-way set associative, 32-byte line size
+ Data TLB: 4 MB pages, 4-way set associative, 8 entries
+ 1st-level instruction cache: 8 KB, 4-way set associative, 32-byte line size */
} else
EAX = EBX = ECX = EDX = 0;
break;
@@ -2398,13 +2437,13 @@ cpu_CPUID(void)
case CPU_PENTIUM2:
if (!EAX) {
EAX = 0x00000002;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV;
} else if (EAX == 2) {
EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
Instruction TLB: 4 MB pages, fully associative, 2 entries
@@ -2421,13 +2460,13 @@ cpu_CPUID(void)
case CPU_PENTIUM2D:
if (!EAX) {
EAX = 0x00000002;
- EBX = 0x756e6547;
+ EBX = 0x756e6547; /* GenuineIntel */
EDX = 0x49656e69;
ECX = 0x6c65746e;
} else if (EAX == 1) {
EAX = CPUID;
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_FXSR | CPUID_CMOV;
} else if (EAX == 2) {
EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
Instruction TLB: 4 MB pages, fully associative, 2 entries
@@ -2452,7 +2491,7 @@ cpu_CPUID(void)
case CPU_CYRIX3S:
switch (EAX) {
case 0:
- EAX = 1;
+ EAX = 0x00000001;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
@@ -2464,9 +2503,9 @@ cpu_CPUID(void)
}
break;
case 1:
- EAX = CPUID;
+ EAX = ((msr.fcr2 & 0x0ff0) ? ((msr.fcr2 & 0x0ff0) | (CPUID & 0xf00f)) : CPUID);
EBX = ECX = 0;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 7))
@@ -2477,7 +2516,7 @@ cpu_CPUID(void)
break;
case 0x80000001:
EAX = CPUID;
- EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW;
+ EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 7))
@@ -2510,9 +2549,12 @@ cpu_ven_reset(void)
switch (cpu_s->cpu_type) {
case CPU_WINCHIP:
case CPU_WINCHIP2:
- msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- if (cpu_s->cpu_type == CPU_WINCHIP2)
- msr.fcr |= (1 << 18) | (1 << 20);
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
+ msr.mcr_ctrl = 0xf8000000;
+ if (cpu_s->cpu_type == CPU_WINCHIP2) {
+ msr.fcr |= (1 << 18) | (1 << 20);
+ msr.mcr_ctrl |= (1 << 17);
+ }
break;
case CPU_K6_2P:
@@ -2552,18 +2594,28 @@ cpu_RDMSR(void)
case CPU_IBM486BL:
EAX = EDX = 0;
switch (ECX) {
+ /* Processor Operation Register */
case 0x1000:
EAX = msr.ibm_por & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff);
break;
+ /* Cache Region Control Register */
case 0x1001:
- EAX = msr.ibm_crcr & 0xffffffffff;
+ EAX = msr.ibm_crcr & 0xffffffff;
+ EDX = (msr.ibm_crcr >> 32) & 0x0000ffff;
break;
+ /* Processor Operation Register */
case 0x1002:
if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi)
EAX = msr.ibm_por2 & 0x3f000000;
break;
+
+ /* Processor Control Register */
+ case 0x1004:
+ if (cpu_s->cpu_type > CPU_IBM486SLC)
+ EAX = msr.ibm_pcr & 0x00d6001a;
+ break;
}
break;
@@ -2571,42 +2623,74 @@ cpu_RDMSR(void)
case CPU_WINCHIP2:
EAX = EDX = 0;
switch (ECX) {
+ /* Pentium Processor Parity Reversal Register */
case 0x02:
EAX = msr.tr1;
break;
+ /* Pentium Processor New Feature Control */
case 0x0e:
EAX = msr.tr12;
break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* Performance Monitor - Control and Event Select */
case 0x11:
EAX = msr.cesr;
break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ EAX = msr.pmc[0] & 0xffffffff;
+ EDX = msr.pmc[0] >> 32;
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ EAX = msr.pmc[1] & 0xffffffff;
+ EDX = msr.pmc[1] >> 32;
+ break;
+ /* Feature Control Register */
case 0x107:
EAX = msr.fcr;
break;
+ /* Feature Control Register 2 */
case 0x108:
EAX = msr.fcr2 & 0xffffffff;
EDX = msr.fcr2 >> 32;
break;
+ /* Feature Control Register 4 */
case 0x10a:
EAX = cpu_multi & 3;
break;
+ /* Memory Configuration Register Control */
+ case 0x120:
+ EAX = msr.mcr_ctrl;
+ break;
+ /* Unknown */
+ case 0x131:
+ case 0x142 ... 0x145:
+ case 0x147:
+ case 0x150:
+ case 0x151:
+ break;
}
break;
case CPU_CYRIX3S:
EAX = EDX = 0;
switch (ECX) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* EBL_CR_POWERON - Processor Hard Power-On Configuration */
case 0x2a:
EAX = 0xc4000000;
EDX = 0;
@@ -2633,29 +2717,41 @@ cpu_RDMSR(void)
if (cpu_busspeed >= 84000000)
EAX |= (1 << 19);
break;
+ /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */
+ case 0xc1:
+ EAX = tsc & 0xffffffff;
+ EDX = (tsc >> 32) & 0xff;
+ break;
+ /* PERFCTR1 - Performance Counter Register 1 */
+ case 0xc2:
+ EAX = msr.perfctr[1] & 0xffffffff;
+ EDX = msr.perfctr[1] >> 32;
+ break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
+ case 0x11e:
+ EAX = 0x800000; /* L2 cache disabled */
+ break;
+ /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */
+ case 0x186:
+ EAX = 0x470079;
+ break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
+ case 0x187:
+ EAX = msr.evntsel[1] & 0xffffffff;
+ EDX = msr.evntsel[1] >> 32;
+ break;
+ /* Feature Control Register */
case 0x1107:
EAX = msr.fcr;
break;
+ /* Feature Control Register 2 */
case 0x1108:
EAX = msr.fcr2 & 0xffffffff;
EDX = msr.fcr2 >> 32;
break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1) {
EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff;
EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32;
@@ -2664,29 +2760,27 @@ cpu_RDMSR(void)
EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32;
}
break;
+ /* MTRRfix64K_00000 */
case 0x250:
EAX = msr.mtrr_fix64k_8000 & 0xffffffff;
EDX = msr.mtrr_fix64k_8000 >> 32;
break;
+ /* MTRRfix16K_80000 */
case 0x258:
EAX = msr.mtrr_fix16k_8000 & 0xffffffff;
EDX = msr.mtrr_fix16k_8000 >> 32;
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
EAX = msr.mtrr_fix16k_a000 & 0xffffffff;
EDX = msr.mtrr_fix16k_a000 >> 32;
break;
- case 0x268:
- case 0x269:
- case 0x26a:
- case 0x26b:
- case 0x26c:
- case 0x26d:
- case 0x26e:
- case 0x26f:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff;
EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32;
break;
+ /* MTRRdefType */
case 0x2ff:
EAX = msr.mtrr_deftype & 0xffffffff;
EDX = msr.mtrr_deftype >> 32;
@@ -2704,37 +2798,75 @@ cpu_RDMSR(void)
case CPU_K6_3:
case CPU_K6_2P:
case CPU_K6_3P:
- EAX = EDX = 0;
+ EAX = 0;
+ /* EDX is left unchanged when reading this MSR! */
+ if (ECX != 0x82)
+ EDX = 0;
switch (ECX) {
+ /* Machine Check Address Register */
case 0x00000000:
+ EAX = msr.mcar & 0xffffffff;
+ EDX = msr.mcar >> 32;
+ break;
+ /* Machine Check Type Register */
case 0x00000001:
+ EAX = msr.mctr & 0xffffffff;
+ EDX = msr.mctr >> 32;
break;
+ /* Test Register 12 */
case 0x0000000e:
EAX = msr.tr12;
break;
+ /* Time Stamp Counter */
case 0x00000010:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* Array Access Register */
+ case 0x00000082:
+ if (cpu_s->cpu_type > CPU_5K86)
+ goto amd_k_invalid_rdmsr;
+ EAX = msr.amd_aar & 0xffffffff;
+ /* EDX is left unchanged! */
+ break;
+ /* Hardware Configuration Register */
case 0x00000083:
- EAX = msr.ecx83 & 0xffffffff;
- EDX = msr.ecx83 >> 32;
+ EAX = msr.amd_hwcr & 0xffffffff;
+ EDX = msr.amd_hwcr >> 32;
break;
+ /* Write Allocate Top-of-Memory and Control Register */
+ case 0x00000085:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_rdmsr;
+ EAX = msr.amd_watmcr & 0xffffffff;
+ EDX = msr.amd_watmcr >> 32;
+ break;
+ /* Write Allocate Programmable Memory Range Register */
+ case 0x00000086:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_rdmsr;
+ EAX = msr.amd_wapmrr & 0xffffffff;
+ EDX = msr.amd_wapmrr >> 32;
+ break;
+ /* Extended Feature Enable Register */
case 0xc0000080:
EAX = msr.amd_efer & 0xffffffff;
EDX = msr.amd_efer >> 32;
break;
+ /* SYSCALL Target Address Register */
case 0xc0000081:
if (cpu_s->cpu_type < CPU_K6_2)
goto amd_k_invalid_rdmsr;
- EAX = msr.star & 0xffffffff;
- EDX = msr.star >> 32;
+ EAX = msr.amd_star & 0xffffffff;
+ EDX = msr.amd_star >> 32;
break;
+ /* Write-Handling Control Register */
case 0xc0000082:
EAX = msr.amd_whcr & 0xffffffff;
EDX = msr.amd_whcr >> 32;
break;
+ /* UC/WC Cacheability Control Register */
case 0xc0000085:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_rdmsr;
@@ -2742,6 +2874,7 @@ cpu_RDMSR(void)
EAX = msr.amd_uwccr & 0xffffffff;
EDX = msr.amd_uwccr >> 32;
break;
+ /* Enhanced Power Management Register */
case 0xc0000086:
if (cpu_s->cpu_type < CPU_K6_2P)
goto amd_k_invalid_rdmsr;
@@ -2749,6 +2882,7 @@ cpu_RDMSR(void)
EAX = msr.amd_epmr & 0xffffffff;
EDX = msr.amd_epmr >> 32;
break;
+ /* Processor State Observability Register */
case 0xc0000087:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_rdmsr;
@@ -2756,6 +2890,7 @@ cpu_RDMSR(void)
EAX = msr.amd_psor & 0xffffffff;
EDX = msr.amd_psor >> 32;
break;
+ /* Page Flush/Invalidate Register */
case 0xc0000088:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_rdmsr;
@@ -2763,6 +2898,7 @@ cpu_RDMSR(void)
EAX = msr.amd_pfir & 0xffffffff;
EDX = msr.amd_pfir >> 32;
break;
+ /* Level-2 Cache Array Access Register */
case 0xc0000089:
if (cpu_s->cpu_type < CPU_K6_3)
goto amd_k_invalid_rdmsr;
@@ -2780,25 +2916,205 @@ cpu_RDMSR(void)
case CPU_P24T:
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
+ EAX = EDX = 0;
+ /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per:
+ Ralf Brown, Pentium Model-Specific Registers and What They Reveal.
+ https://www.cs.cmu.edu/~ralf/papers/highmsr.html
+ But leave the bit 31 intact to be able to handle both low and high
+ MSRs in a single switch block. */
+ switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) {
+ /* Machine Check Exception Address */
+ case 0x00000000:
+ case 0x80000000:
+ EAX = msr.mcar & 0xffffffff;
+ EDX = msr.mcar >> 32;
+ break;
+ /* Machine Check Exception Type */
+ case 0x00000001:
+ case 0x80000001:
+ EAX = msr.mctr & 0xffffffff;
+ EDX = msr.mctr >> 32;
+ msr.mctr &= ~0x1; /* clear the machine check pending bit */
+ break;
+ /* TR1 - Parity Reversal Test Register */
+ case 0x00000002:
+ case 0x80000002:
+ EAX = msr.tr1;
+ break;
+ /* TR2 - Instruction Cache End Bit */
+ case 0x00000004:
+ case 0x80000004:
+ if (cpu_s->cpu_type == CPU_PENTIUMMMX)
+ goto pentium_invalid_rdmsr;
+ EAX = msr.tr2;
+ break;
+ /* TR3 - Cache Test Data */
+ case 0x00000005:
+ case 0x80000005:
+ EAX = msr.tr3;
+ break;
+ /* TR4 - Cache Test Tag */
+ case 0x00000006:
+ case 0x80000006:
+ EAX = msr.tr4;
+ break;
+ /* TR5 - Cache Test Control */
+ case 0x00000007:
+ case 0x80000007:
+ EAX = msr.tr5;
+ break;
+ /* TR6 - TLB Test Command */
+ case 0x00000008:
+ case 0x80000008:
+ EAX = msr.tr6;
+ break;
+ /* TR7 - TLB Test Data */
+ case 0x00000009:
+ case 0x80000009:
+ EAX = msr.tr7;
+ break;
+ /* TR9 - Branch Target Buffer Tag */
+ case 0x0000000b:
+ case 0x8000000b:
+ EAX = msr.tr9;
+ break;
+ /* TR10 - Branch Target Buffer Target */
+ case 0x0000000c:
+ case 0x8000000c:
+ EAX = msr.tr10;
+ break;
+ /* TR11 - Branch Target Buffer Control */
+ case 0x0000000d:
+ case 0x8000000d:
+ EAX = msr.tr11;
+ break;
+ /* TR12 - New Feature Control */
+ case 0x0000000e:
+ case 0x8000000e:
+ EAX = msr.tr12;
+ break;
+ /* Time Stamp Counter */
+ case 0x00000010:
+ case 0x80000010:
+ EAX = tsc & 0xffffffff;
+ EDX = tsc >> 32;
+ break;
+ /* Performance Monitor - Control and Event Select */
+ case 0x00000011:
+ case 0x80000011:
+ EAX = msr.cesr;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x00000012:
+ case 0x80000012:
+ EAX = msr.pmc[0] & 0xffffffff;
+ EDX = msr.pmc[0] >> 32;
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x00000013:
+ case 0x80000013:
+ EAX = msr.pmc[1] & 0xffffffff;
+ EDX = msr.pmc[1] >> 32;
+ break;
+ /* Unknown */
+ case 0x00000014:
+ case 0x80000014:
+ if ((CPUID & 0xfff) <= 0x520)
+ goto pentium_invalid_rdmsr;
+ break;
+ /* Unknown, possibly paging-related; initial value is 0004h,
+ becomes 0008h once paging is enabled */
+ case 0x80000018:
+ EAX = ((cr0 & (1 << 31)) ? 0x00000008 : 0x00000004);
+ break;
+ /* Floating point - last prefetched opcode
+ bits 10-8: low three bits of first byte of FP instruction
+ bits 7-0: second byte of floating-point instruction */
+ case 0x80000019:
+ EAX = 0;
+ break;
+ /* Floating point - last executed non-control opcode */
+ case 0x8000001a:
+ EAX = 0;
+ break;
+ /* Floating point - last non-control exception opcode - part
+ of FSTENV/FSAVE'd environment */
+ case 0x8000001b:
+ EAX = msr.fp_last_xcpt;
+ break;
+ /* Unknown */
+ case 0x8000001c:
+ EAX = 0x00000004;
+ break;
+ /* Probe Mode Control */
+ case 0x8000001d:
+ EAX = msr.probe_ctl;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001e:
+ EAX = msr.ecx8000001e;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001f:
+ EAX = msr.ecx8000001f;
+ break;
+ /* Reserved/Unimplemented */
+ case 0x80000003:
+ case 0x8000000a:
+ case 0x8000000f:
+ case 0x80000015 ... 0x80000017:
+ EAX = (ECX & 0x1f) * 2;
+ break;
+ default:
+pentium_invalid_rdmsr:
+ cpu_log("RDMSR: Invalid MSR: %08X\n", ECX);
+ x86gpf(NULL, 0);
+ break;
+ }
+ cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
+ break;
+
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
case CPU_Cx6x86:
case CPU_Cx6x86L:
case CPU_CxGX1:
case CPU_Cx6x86MX:
- if (cpu_s->cpu_type < CPU_Cx6x86)
-#endif
- EAX = EDX = 0;
switch (ECX) {
- case 0x00:
- case 0x01:
+ /* Test Data */
+ case 0x03:
+ EAX = msr.tr3;
+ break;
+ /* Test Address */
+ case 0x04:
+ EAX = msr.tr4;
break;
+ /* Test Command/Status */
+ case 0x05:
+ EAX = msr.tr5;
+ break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* Performance Monitor - Control and Event Select */
+ case 0x11:
+ EAX = msr.cesr;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ EAX = msr.pmc[0] & 0xffffffff;
+ EDX = msr.pmc[0] >> 32;
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ EAX = msr.pmc[1] & 0xffffffff;
+ EDX = msr.pmc[1] >> 32;
+ break;
}
cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
break;
+#endif
case CPU_PENTIUMPRO:
case CPU_PENTIUM2:
@@ -2807,32 +3123,46 @@ cpu_RDMSR(void)
/* Per RichardG's probing of a real Deschutes using my RDMSR tool,
we have discovered that the top 18 bits are filtered out. */
switch (ECX & 0x00003fff) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
break;
+ /* Time Stamp Counter */
case 0x10:
EAX = tsc & 0xffffffff;
EDX = tsc >> 32;
break;
+ /* IA32_PLATFORM_ID - Platform ID */
case 0x17:
- if (cpu_s->cpu_type != CPU_PENTIUM2D)
+ if (cpu_s->cpu_type < CPU_PENTIUM2D)
goto i686_invalid_rdmsr;
if (cpu_f->package == CPU_PKG_SLOT2)
- EDX |= 0x80000;
+ EDX |= (1 << 19);
else if (cpu_f->package == CPU_PKG_SOCKET370)
- EDX |= 0x100000;
+ EDX |= (1 << 20);
+ break;
+ /* Unknown */
+ case 0x18:
break;
+ /* IA32_APIC_BASE - APIC Base Address */
case 0x1B:
EAX = msr.apic_base & 0xffffffff;
EDX = msr.apic_base >> 32;
cpu_log("APIC_BASE read : %08X%08X\n", EDX, EAX);
break;
- /* Unknown (undocumented?) MSR used by the Hyper-V BIOS. */
+ /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */
case 0x20:
EAX = msr.ecx20 & 0xffffffff;
EDX = msr.ecx20 >> 32;
break;
+ /* Unknown */
+ case 0x21:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_rdmsr;
+ break;
+ /* EBL_CR_POWERON - Processor Hard Power-On Configuration */
case 0x2a:
EAX = 0xc4000000;
EDX = 0;
@@ -2867,47 +3197,85 @@ cpu_RDMSR(void)
EAX |= (1 << 19);
}
break;
+ /* Unknown */
+ case 0x32:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_rdmsr;
+ break;
+ /* TEST_CTL - Test Control Register */
+ case 0x33:
+ EAX = msr.test_ctl;
+ break;
+ /* Unknown */
+ case 0x34:
+ case 0x3a:
+ case 0x3b:
+ case 0x50 ... 0x54:
+ break;
+ /* BIOS_UPDT_TRIG - BIOS Update Trigger */
case 0x79:
- EAX = msr.ecx79 & 0xffffffff;
- EDX = msr.ecx79 >> 32;
+ EAX = msr.bios_updt & 0xffffffff;
+ EDX = msr.bios_updt >> 32;
break;
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- EAX = msr.ecx8x[ECX - 0x88] & 0xffffffff;
- EDX = msr.ecx8x[ECX - 0x88] >> 32;
+ /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register
+ 8Bh: BIOS_SIGN - BIOS Update Signature */
+ case 0x88 ... 0x8b:
+ EAX = msr.bbl_cr_dx[ECX - 0x88] & 0xffffffff;
+ EDX = msr.bbl_cr_dx[ECX - 0x88] >> 32;
break;
+ /* Unknown */
+ case 0xae:
+ break;
+ /* PERFCTR0 - Performance Counter Register 0 */
case 0xc1:
+ /* PERFCTR1 - Performance Counter Register 1 */
case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- EAX = msr.ia32_pmc[ECX - 0xC1] & 0xffffffff;
- EDX = msr.ia32_pmc[ECX - 0xC1] >> 32;
+ EAX = msr.perfctr[ECX - 0xC1] & 0xffffffff;
+ EDX = msr.perfctr[ECX - 0xC1] >> 32;
break;
+ /* MTRRcap */
case 0xfe:
EAX = msr.mtrr_cap & 0xffffffff;
EDX = msr.mtrr_cap >> 32;
break;
+ /* BBL_CR_ADDR - L2 Cache Address Register */
case 0x116:
- EAX = msr.ecx116 & 0xffffffff;
- EDX = msr.ecx116 >> 32;
+ EAX = msr.bbl_cr_addr & 0xffffffff;
+ EDX = msr.bbl_cr_addr >> 32;
break;
+ /* BBL_CR_DECC - L2 Cache Date ECC Register */
case 0x118:
+ EAX = msr.bbl_cr_decc & 0xffffffff;
+ EDX = msr.bbl_cr_decc >> 32;
+ break;
+ /* BBL_CR_CTL - L2 Cache Control Register */
case 0x119:
+ EAX = msr.bbl_cr_ctl & 0xffffffff;
+ EDX = msr.bbl_cr_ctl >> 32;
+ break;
+ /* BBL_CR_TRIG - L2 Cache Trigger Register */
case 0x11a:
+ EAX = msr.bbl_cr_trig & 0xffffffff;
+ EDX = msr.bbl_cr_trig >> 32;
+ break;
+ /* BBL_CR_BUSY - L2 Cache Busy Register */
case 0x11b:
- EAX = msr.ecx11x[ECX - 0x118] & 0xffffffff;
- EDX = msr.ecx11x[ECX - 0x118] >> 32;
+ EAX = msr.bbl_cr_busy & 0xffffffff;
+ EDX = msr.bbl_cr_busy >> 32;
break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
case 0x11e:
- EAX = msr.ecx11e & 0xffffffff;
- EDX = msr.ecx11e >> 32;
+ EAX = msr.bbl_cr_ctl3 & 0xffffffff;
+ EDX = msr.bbl_cr_ctl3 >> 32;
+ break;
+ /* Unknown */
+ case 0x131:
+ case 0x14e ... 0x151:
+ case 0x154:
+ case 0x15b:
+ case 0x15f:
break;
+ /* SYSENTER_CS - SYSENTER target CS */
case 0x174:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_rdmsr;
@@ -2916,6 +3284,7 @@ cpu_RDMSR(void)
EAX |= msr.sysenter_cs;
EDX = 0x00000000;
break;
+ /* SYSENTER_ESP - SYSENTER target ESP */
case 0x175:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_rdmsr;
@@ -2923,6 +3292,7 @@ cpu_RDMSR(void)
EAX = msr.sysenter_esp;
EDX = 0x00000000;
break;
+ /* SYSENTER_EIP - SYSENTER target EIP */
case 0x176:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_rdmsr;
@@ -2930,48 +3300,49 @@ cpu_RDMSR(void)
EAX = msr.sysenter_eip;
EDX = 0x00000000;
break;
+ /* MCG_CAP - Machine Check Global Capability */
case 0x179:
EAX = 0x00000105;
EDX = 0x00000000;
break;
+ /* MCG_STATUS - Machine Check Global Status */
case 0x17a:
break;
+ /* MCG_CTL - Machine Check Global Control */
case 0x17b:
EAX = msr.mcg_ctl & 0xffffffff;
EDX = msr.mcg_ctl >> 32;
break;
+ /* EVNTSEL0 - Performance Counter Event Select 0 */
case 0x186:
- EAX = msr.ecx186 & 0xffffffff;
- EDX = msr.ecx186 >> 32;
- break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
case 0x187:
- EAX = msr.ecx187 & 0xffffffff;
- EDX = msr.ecx187 >> 32;
+ EAX = msr.evntsel[ECX - 0x186] & 0xffffffff;
+ EDX = msr.evntsel[ECX - 0x186] >> 32;
break;
- case 0x1d9:
- EAX = msr.debug_ctl & 0xffffffff;
- EDX = msr.debug_ctl >> 32;
+ /* Unknown */
+ case 0x1d3:
break;
+ /* DEBUGCTLMSR - Debugging Control Register */
+ case 0x1d9:
+ EAX = msr.debug_ctl;
+ break;
+ /* LASTBRANCHFROMIP - address from which a branch was last taken */
+ case 0x1db:
+ /* LASTBRANCHTOIP - destination address of the last taken branch instruction */
+ case 0x1dc:
+ /* LASTINTFROMIP - address at which an interrupt last occurred */
+ case 0x1dd:
+ /* LASTINTTOIP - address to which the last interrupt caused a branch */
+ case 0x1de:
+ break;
+ /* ROB_CR_BKUPTMPDR6 */
case 0x1e0:
- EAX = msr.ecx1e0 & 0xffffffff;
- EDX = msr.ecx1e0 >> 32;
- break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ EAX = msr.rob_cr_bkuptmpdr6;
+ break;
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1) {
EAX = msr.mtrr_physmask[(ECX - 0x200) >> 1] & 0xffffffff;
EDX = msr.mtrr_physmask[(ECX - 0x200) >> 1] >> 32;
@@ -2980,60 +3351,88 @@ cpu_RDMSR(void)
EDX = msr.mtrr_physbase[(ECX - 0x200) >> 1] >> 32;
}
break;
+ /* MTRRfix64K_00000 */
case 0x250:
EAX = msr.mtrr_fix64k_8000 & 0xffffffff;
EDX = msr.mtrr_fix64k_8000 >> 32;
break;
+ /* MTRRfix16K_80000 */
case 0x258:
EAX = msr.mtrr_fix16k_8000 & 0xffffffff;
EDX = msr.mtrr_fix16k_8000 >> 32;
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
EAX = msr.mtrr_fix16k_a000 & 0xffffffff;
EDX = msr.mtrr_fix16k_a000 >> 32;
break;
- case 0x268:
- case 0x269:
- case 0x26a:
- case 0x26b:
- case 0x26c:
- case 0x26d:
- case 0x26e:
- case 0x26f:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
EAX = msr.mtrr_fix4k[ECX - 0x268] & 0xffffffff;
EDX = msr.mtrr_fix4k[ECX - 0x268] >> 32;
break;
+ /* Page Attribute Table */
case 0x277:
+ if (cpu_s->cpu_type < CPU_PENTIUM2D)
+ goto i686_invalid_rdmsr;
EAX = msr.pat & 0xffffffff;
EDX = msr.pat >> 32;
break;
+ /* Unknown */
+ case 0x280:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_rdmsr;
+ break;
+ /* MTRRdefType */
case 0x2ff:
EAX = msr.mtrr_deftype & 0xffffffff;
EDX = msr.mtrr_deftype >> 32;
break;
+ /* MC0_CTL - Machine Check 0 Control */
case 0x400:
+ /* MC1_CTL - Machine Check 1 Control */
case 0x404:
+ /* MC2_CTL - Machine Check 2 Control */
case 0x408:
+ /* MC4_CTL - Machine Check 4 Control */
case 0x40c:
+ /* MC3_CTL - Machine Check 3 Control */
case 0x410:
EAX = msr.mca_ctl[(ECX - 0x400) >> 2] & 0xffffffff;
EDX = msr.mca_ctl[(ECX - 0x400) >> 2] >> 32;
break;
+ /* MC0_STATUS - Machine Check 0 Status */
case 0x401:
+ /* MC0_ADDR - Machine Check 0 Address */
case 0x402:
+ /* MC1_STATUS - Machine Check 1 Status */
case 0x405:
+ /* MC1_ADDR - Machine Check 1 Address */
case 0x406:
- case 0x407:
+ /* MC2_STATUS - Machine Check 2 Status */
case 0x409:
+ /* MC2_ADDR - Machine Check 2 Address */
+ case 0x40a:
+ /* MC4_STATUS - Machine Check 4 Status */
case 0x40d:
+ /* MC4_ADDR - Machine Check 4 Address */
case 0x40e:
+ /* MC3_STATUS - Machine Check 3 Status */
case 0x411:
+ /* MC3_ADDR - Machine Check 3 Address */
case 0x412:
break;
+ /* Unknown */
case 0x570:
EAX = msr.ecx570 & 0xffffffff;
EDX = msr.ecx570 >> 32;
break;
+ /* Unknown, possibly debug registers? */
+ case 0x1000 ... 0x1007:
+ /* Unknown, possibly control registers? */
+ case 0x2000:
+ case 0x2002 ... 0x2004:
+ break;
default:
i686_invalid_rdmsr:
cpu_log("RDMSR: Invalid MSR: %08X\n", ECX);
@@ -3055,38 +3454,59 @@ cpu_WRMSR(void)
switch (cpu_s->cpu_type) {
case CPU_IBM386SLC:
- case CPU_IBM486BL:
case CPU_IBM486SLC:
+ case CPU_IBM486BL:
switch (ECX) {
+ /* Processor Operation Register */
case 0x1000:
msr.ibm_por = EAX & ((cpu_s->cpu_type > CPU_IBM386SLC) ? 0xffeff : 0xfeff);
cpu_cache_int_enabled = (EAX & (1 << 7));
break;
+ /* Cache Region Control Register */
case 0x1001:
- msr.ibm_crcr = EAX & 0xffffffffff;
+ msr.ibm_crcr = EAX | ((uint64_t) (EDX & 0x0000ffff) << 32);
break;
+ /* Processor Operation Register */
case 0x1002:
if ((cpu_s->cpu_type > CPU_IBM386SLC) && cpu_s->multi)
msr.ibm_por2 = EAX & 0x3f000000;
break;
+ /* Processor Control Register */
+ case 0x1004:
+ if (cpu_s->cpu_type > CPU_IBM486SLC)
+ msr.ibm_pcr = EAX & 0x00d6001a;
+ break;
}
break;
case CPU_WINCHIP:
case CPU_WINCHIP2:
switch (ECX) {
+ /* Pentium Processor Parity Reversal Register */
case 0x02:
msr.tr1 = EAX & 2;
break;
+ /* Pentium Processor New Feature Control */
case 0x0e:
- msr.tr12 = EAX & 0x228;
+ msr.tr12 = EAX & 0x248;
break;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
+ /* Performance Monitor - Control and Event Select */
case 0x11:
msr.cesr = EAX & 0xff00ff;
break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ msr.pmc[0] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ msr.pmc[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Feature Control Register */
case 0x107:
msr.fcr = EAX;
if (EAX & (1 << 9))
@@ -3106,23 +3526,67 @@ cpu_WRMSR(void)
else
CPUID = cpu_s->cpuid_model;
break;
+ /* Feature Control Register 2 */
case 0x108:
msr.fcr2 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Feature Control Register 3 */
case 0x109:
msr.fcr3 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Memory Configuration Register 0..7 */
+ case 0x110 ... 0x117:
+ temp = ECX - 0x110;
+ if (cpu_s->cpu_type == CPU_WINCHIP2) {
+ if (EAX & 0x1f)
+ msr.mcr_ctrl |= (1 << (temp + 9));
+ else
+ msr.mcr_ctrl &= ~(1 << (temp + 9));
+ }
+ msr.mcr[temp] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Memory Configuration Register Control */
+ case 0x120:
+ msr.mcr_ctrl = EAX & ((cpu_s->cpu_type == CPU_WINCHIP2) ? 0x1df : 0x1f);
+ break;
+ /* Unknown */
+ case 0x131:
+ case 0x142 ... 0x145:
+ case 0x147:
+ case 0x150:
+ case 0x151:
+ break;
}
break;
case CPU_CYRIX3S:
switch (ECX) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
break;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
+ /* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */
+ case 0xc1:
+ break;
+ /* PERFCTR0 - Performance Counter Register 1 */
+ case 0xc2:
+ msr.perfctr[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
+ case 0x11e:
+ /* EVNTSEL0 - Performance Counter Event Select 0 - hardcoded */
+ case 0x186:
+ break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
+ case 0x187:
+ msr.evntsel[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Feature Control Register */
case 0x1107:
msr.fcr = EAX;
if (EAX & (1 << 1))
@@ -3134,52 +3598,39 @@ cpu_WRMSR(void)
else
cpu_CR4_mask &= ~CR4_PGE;
break;
+ /* Feature Control Register 2 */
case 0x1108:
msr.fcr2 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Feature Control Register 3 */
case 0x1109:
msr.fcr3 = EAX | ((uint64_t) EDX << 32);
break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1)
msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
else
msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix64K_00000 */
case 0x250:
msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_80000 */
case 0x258:
msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32);
break;
- case 0x268:
- case 0x269:
- case 0x26A:
- case 0x26B:
- case 0x26C:
- case 0x26D:
- case 0x26E:
- case 0x26F:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRdefType */
case 0x2ff:
msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32);
break;
@@ -3197,18 +3648,47 @@ cpu_WRMSR(void)
case CPU_K6_2P:
case CPU_K6_3P:
switch (ECX) {
- case 0x00:
- case 0x01:
+ /* Machine Check Address Register */
+ case 0x00000000:
+ if (cpu_s->cpu_type > CPU_5K86)
+ msr.mcar = EAX | ((uint64_t) EDX << 32);
break;
- case 0x0e:
- msr.tr12 = EAX & 0x228;
+ /* Machine Check Type Register */
+ case 0x00000001:
+ if (cpu_s->cpu_type > CPU_5K86)
+ msr.mctr = EAX | ((uint64_t) EDX << 32);
break;
- case 0x10:
+ /* Test Register 12 */
+ case 0x0000000e:
+ msr.tr12 = EAX & 0x8;
+ break;
+ /* Time Stamp Counter */
+ case 0x00000010:
tsc = EAX | ((uint64_t) EDX << 32);
break;
- case 0x83:
- msr.ecx83 = EAX | ((uint64_t) EDX << 32);
+ /* Array Access Register */
+ case 0x00000082:
+ if (cpu_s->cpu_type > CPU_5K86)
+ goto amd_k_invalid_wrmsr;
+ msr.amd_aar = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Hardware Configuration Register */
+ case 0x00000083:
+ msr.amd_hwcr = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Write Allocate Top-of-Memory and Control Register */
+ case 0x00000085:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_wrmsr;
+ msr.amd_watmcr = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Write Allocate Programmable Memory Range Register */
+ case 0x00000086:
+ if (cpu_s->cpu_type != CPU_5K86)
+ goto amd_k_invalid_wrmsr;
+ msr.amd_wapmrr = EAX | ((uint64_t) EDX << 32);
break;
+ /* Extended Feature Enable Register */
case 0xc0000080:
temp = EAX | ((uint64_t) EDX << 32);
if (temp & ~1ULL)
@@ -3216,39 +3696,46 @@ cpu_WRMSR(void)
else
msr.amd_efer = temp;
break;
+ /* SYSCALL Target Address Register */
case 0xc0000081:
if (cpu_s->cpu_type < CPU_K6_2)
goto amd_k_invalid_wrmsr;
- msr.star = EAX | ((uint64_t) EDX << 32);
+ msr.amd_star = EAX | ((uint64_t) EDX << 32);
break;
+ /* Write-Handling Control Register */
case 0xc0000082:
msr.amd_whcr = EAX | ((uint64_t) EDX << 32);
break;
+ /* UC/WC Cacheability Control Register */
case 0xc0000085:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_wrmsr;
msr.amd_uwccr = EAX | ((uint64_t) EDX << 32);
break;
+ /* Enhanced Power Management Register */
case 0xc0000086:
if (cpu_s->cpu_type < CPU_K6_2P)
goto amd_k_invalid_wrmsr;
msr.amd_epmr = EAX | ((uint64_t) EDX << 32);
break;
+ /* Processor State Observability Register */
case 0xc0000087:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_wrmsr;
msr.amd_psor = EAX | ((uint64_t) EDX << 32);
break;
+ /* Page Flush/Invalidate Register */
case 0xc0000088:
if (cpu_s->cpu_type < CPU_K6_2C)
goto amd_k_invalid_wrmsr;
msr.amd_pfir = EAX | ((uint64_t) EDX << 32);
break;
+ /* Level-2 Cache Array Access Register */
case 0xc0000089:
if (cpu_s->cpu_type < CPU_K6_3)
goto amd_k_invalid_wrmsr;
@@ -3265,32 +3752,190 @@ cpu_WRMSR(void)
case CPU_P24T:
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
+ cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
+ /* Filter out the upper 27 bits when ECX value is over 0x80000000, as per:
+ Ralf Brown, Pentium Model-Specific Registers and What They Reveal.
+ https://www.cs.cmu.edu/~ralf/papers/highmsr.html
+ But leave the bit 31 intact to be able to handle both low and high
+ MSRs in a single switch block. */
+ switch (ECX & (ECX > 0x7fffffff ? 0x8000001f : 0x7fffffff)) {
+ /* Machine Check Exception Address */
+ case 0x00000000:
+ case 0x80000000:
+ /* Machine Check Exception Type */
+ case 0x00000001:
+ case 0x80000001:
+ break;
+ /* TR1 - Parity Reversal Test Register */
+ case 0x00000002:
+ case 0x80000002:
+ msr.tr1 = EAX & 0x3fff;
+ break;
+ /* TR2 - Instruction Cache End Bit */
+ case 0x00000004:
+ case 0x80000004:
+ if (cpu_s->cpu_type == CPU_PENTIUMMMX)
+ goto pentium_invalid_wrmsr;
+ msr.tr2 = EAX & 0xf;
+ break;
+ /* TR3 - Cache Test Data */
+ case 0x00000005:
+ case 0x80000005:
+ msr.tr3 = EAX;
+ break;
+ /* TR4 - Cache Test Tag */
+ case 0x00000006:
+ case 0x80000006:
+ msr.tr4 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffff1f : 0xffffff07);
+ break;
+ /* TR5 - Cache Test Control */
+ case 0x00000007:
+ case 0x80000007:
+ msr.tr5 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0x87fff : 0x7fff);
+ break;
+ /* TR6 - TLB Test Command */
+ case 0x00000008:
+ case 0x80000008:
+ msr.tr6 = EAX & 0xffffff07;
+ break;
+ /* TR7 - TLB Test Data */
+ case 0x00000009:
+ case 0x80000009:
+ msr.tr7 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xfffffc7f : 0xffffff9c);
+ break;
+ /* TR9 - Branch Target Buffer Tag */
+ case 0x0000000b:
+ case 0x8000000b:
+ msr.tr9 = EAX & ((cpu_s->cpu_type == CPU_PENTIUMMMX) ? 0xffffffff : 0xffffffc3);
+ break;
+ /* TR10 - Branch Target Buffer Target */
+ case 0x0000000c:
+ case 0x8000000c:
+ msr.tr10 = EAX;
+ break;
+ /* TR11 - Branch Target Buffer Control */
+ case 0x0000000d:
+ case 0x8000000d:
+ msr.tr11 = EAX & ((cpu_s->cpu_type >= CPU_PENTIUMMMX) ? 0x3001fcf : 0xfcf);
+ break;
+ /* TR12 - New Feature Control */
+ case 0x0000000e:
+ case 0x8000000e:
+ if (cpu_s->cpu_type == CPU_PENTIUMMMX)
+ temp = EAX & 0x38034f;
+ else if ((CPUID & 0xfff) >= 0x52b)
+ temp = EAX & 0x20435f;
+ else if ((CPUID & 0xfff) >= 0x520)
+ temp = EAX & 0x20035f;
+ else
+ temp = EAX & 0x20030f;
+ msr.tr12 = temp;
+ break;
+ /* Time Stamp Counter */
+ case 0x00000010:
+ case 0x80000010:
+ tsc = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Control and Event Select */
+ case 0x00000011:
+ case 0x80000011:
+ msr.cesr = EAX & 0x3ff03ff;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x00000012:
+ case 0x80000012:
+ msr.pmc[0] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x00000013:
+ case 0x80000013:
+ msr.pmc[1] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Unknown */
+ case 0x00000014:
+ case 0x80000014:
+ if ((CPUID & 0xfff) <= 0x520)
+ goto pentium_invalid_wrmsr;
+ break;
+ /* Unknown, possibly paging-related; initial value is 0004h,
+ becomes 0008h once paging is enabled */
+ case 0x80000018:
+ /* Floating point - last prefetched opcode
+ bits 10-8: low three bits of first byte of FP instruction
+ bits 7-0: second byte of floating-point instruction */
+ case 0x80000019:
+ /* Floating point - last executed non-control opcode */
+ case 0x8000001a:
+ break;
+ /* Floating point - last non-control exception opcode - part
+ of FSTENV/FSAVE'd environment */
+ case 0x8000001b:
+ EAX = msr.fp_last_xcpt & 0x7ff;
+ break;
+ /* Unknown */
+ case 0x8000001c:
+ break;
+ /* Probe Mode Control */
+ case 0x8000001d:
+ EAX = msr.probe_ctl & 0x7;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001e:
+ msr.ecx8000001e = EAX;
+ break;
+ /* Unknown, possibly scratchpad register */
+ case 0x8000001f:
+ msr.ecx8000001f = EAX;
+ break;
+ /* Reserved/Unimplemented */
+ case 0x80000003:
+ case 0x8000000a:
+ case 0x8000000f:
+ case 0x80000015 ... 0x80000017:
+ break;
+ default:
+pentium_invalid_wrmsr:
+ cpu_log("WRMSR: Invalid MSR: %08X\n", ECX);
+ x86gpf(NULL, 0);
+ break;
+ }
+ break;
+
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
case CPU_Cx6x86:
case CPU_Cx6x86L:
case CPU_CxGX1:
case CPU_Cx6x86MX:
-#endif
cpu_log("WRMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX);
switch (ECX) {
- case 0x00:
- case 0x01:
- break;
+ /* Test Data */
+ case 0x03:
+ msr.tr3 = EAX;
+ /* Test Address */
+ case 0x04:
+ msr.tr4 = EAX;
+ /* Test Command/Status */
+ case 0x05:
+ msr.tr5 = EAX & 0x008f0f3b;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
- case 0x8b:
-#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
- if (cpu_s->cpu_type < CPU_Cx6x86) {
-#endif
- cpu_log("WRMSR: Invalid MSR: 0x8B\n");
- x86gpf(NULL, 0); /* Needed for Vista to correctly break on Pentium */
-#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
- }
-#endif
+ /* Performance Monitor - Control and Event Select */
+ case 0x11:
+ msr.cesr = EAX & 0x7ff07ff;
+ break;
+ /* Performance Monitor - Event Counter 0 */
+ case 0x12:
+ msr.pmc[0] = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* Performance Monitor - Event Counter 1 */
+ case 0x13:
+ msr.pmc[1] = EAX | ((uint64_t) EDX << 32);
break;
}
break;
+#endif
case CPU_PENTIUMPRO:
case CPU_PENTIUM2:
@@ -3298,168 +3943,240 @@ cpu_WRMSR(void)
/* Per RichardG's probing of a real Deschutes using my RDMSR tool,
we have discovered that the top 18 bits are filtered out. */
switch (ECX & 0x00003fff) {
+ /* Machine Check Exception Address */
case 0x00:
+ /* Machine Check Exception Type */
case 0x01:
if (EAX || EDX)
x86gpf(NULL, 0);
break;
+ /* Time Stamp Counter */
case 0x10:
tsc = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x18:
+ break;
+ /* IA32_APIC_BASE - APIC Base Address */
case 0x1b:
cpu_log("APIC_BASE write: %08X%08X\n", EDX, EAX);
#if 0
msr.apic_base = EAX | ((uint64_t) EDX << 32);
#endif
break;
- /* Unknown (undocumented?) MSR used by the Hyper-V BIOS. */
+ /* Unknown (undocumented?) MSR used by the Hyper-V BIOS */
case 0x20:
msr.ecx20 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x21:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_wrmsr;
+ break;
+ /* EBL_CR_POWERON - Processor Hard Power-On Configuration */
case 0x2a:
break;
+ /* Unknown */
+ case 0x32:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_wrmsr;
+ break;
+ /* TEST_CTL - Test Control Register */
+ case 0x33:
+ msr.test_ctl = EAX;
+ break;
+ /* Unknown */
+ case 0x34:
+ case 0x3a:
+ case 0x3b:
+ case 0x50 ... 0x54:
+ break;
+ /* BIOS_UPDT_TRIG - BIOS Update Trigger */
case 0x79:
- msr.ecx79 = EAX | ((uint64_t) EDX << 32);
+ msr.bios_updt = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_D0 ... BBL_CR_D3 - Chunk 0..3 Data Register
+ 8Bh: BIOS_SIGN - BIOS Update Signature */
+ case 0x88 ... 0x8b:
+ msr.bbl_cr_dx[ECX - 0x88] = EAX | ((uint64_t) EDX << 32);
break;
- case 0x88:
- case 0x89:
- case 0x8a:
- case 0x8b:
- msr.ecx8x[ECX - 0x88] = EAX | ((uint64_t) EDX << 32);
+ /* Unknown */
+ case 0xae:
break;
+ /* PERFCTR0 - Performance Counter Register 0 */
case 0xc1:
+ /* PERFCTR1 - Performance Counter Register 1 */
case 0xc2:
- case 0xc3:
- case 0xc4:
- case 0xc5:
- case 0xc6:
- case 0xc7:
- case 0xc8:
- msr.ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32);
+ msr.perfctr[ECX - 0xC1] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRcap */
case 0xfe:
msr.mtrr_cap = EAX | ((uint64_t) EDX << 32);
break;
+ /* BBL_CR_ADDR - L2 Cache Address Register */
case 0x116:
- msr.ecx116 = EAX | ((uint64_t) EDX << 32);
+ msr.bbl_cr_addr = EAX | ((uint64_t) EDX << 32);
break;
+ /* BBL_CR_DECC - L2 Cache Date ECC Register */
case 0x118:
+ msr.bbl_cr_decc = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_CTL - L2 Cache Control Register */
case 0x119:
+ msr.bbl_cr_ctl = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_TRIG - L2 Cache Trigger Register */
case 0x11a:
+ msr.bbl_cr_trig = EAX | ((uint64_t) EDX << 32);
+ break;
+ /* BBL_CR_BUSY - L2 Cache Busy Register */
case 0x11b:
- msr.ecx11x[ECX - 0x118] = EAX | ((uint64_t) EDX << 32);
+ msr.bbl_cr_busy = EAX | ((uint64_t) EDX << 32);
break;
+ /* BBL_CR_CTL3 - L2 Cache Control Register 3 */
case 0x11e:
- msr.ecx11e = EAX | ((uint64_t) EDX << 32);
+ msr.bbl_cr_ctl3 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x131:
+ case 0x14e ... 0x151:
+ case 0x154:
+ case 0x15b:
+ case 0x15f:
+ break;
+ /* SYSENTER_CS - SYSENTER target CS */
case 0x174:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_wrmsr;
msr.sysenter_cs = EAX & 0xFFFF;
break;
+ /* SYSENTER_ESP - SYSENTER target ESP */
case 0x175:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_wrmsr;
msr.sysenter_esp = EAX;
break;
+ /* SYSENTER_EIP - SYSENTER target EIP */
case 0x176:
if (cpu_s->cpu_type == CPU_PENTIUMPRO)
goto i686_invalid_wrmsr;
msr.sysenter_eip = EAX;
break;
+ /* MCG_CAP - Machine Check Global Capability */
case 0x179:
break;
+ /* MCG_STATUS - Machine Check Global Status */
case 0x17a:
if (EAX || EDX)
x86gpf(NULL, 0);
break;
+ /* MCG_CTL - Machine Check Global Control */
case 0x17b:
msr.mcg_ctl = EAX | ((uint64_t) EDX << 32);
break;
+ /* EVNTSEL0 - Performance Counter Event Select 0 */
case 0x186:
- msr.ecx186 = EAX | ((uint64_t) EDX << 32);
- break;
+ /* EVNTSEL1 - Performance Counter Event Select 1 */
case 0x187:
- msr.ecx187 = EAX | ((uint64_t) EDX << 32);
+ msr.evntsel[ECX - 0x186] = EAX | ((uint64_t) EDX << 32);
+ break;
+ case 0x1d3:
break;
+ /* DEBUGCTLMSR - Debugging Control Register */
case 0x1d9:
- msr.debug_ctl = EAX | ((uint64_t) EDX << 32);
+ msr.debug_ctl = EAX;
break;
+ /* ROB_CR_BKUPTMPDR6 */
case 0x1e0:
- msr.ecx1e0 = EAX | ((uint64_t) EDX << 32);
- break;
- case 0x200:
- case 0x201:
- case 0x202:
- case 0x203:
- case 0x204:
- case 0x205:
- case 0x206:
- case 0x207:
- case 0x208:
- case 0x209:
- case 0x20a:
- case 0x20b:
- case 0x20c:
- case 0x20d:
- case 0x20e:
- case 0x20f:
+ msr.rob_cr_bkuptmpdr6 = EAX;
+ break;
+ /* ECX & 0: MTRRphysBase0 ... MTRRphysBase7
+ ECX & 1: MTRRphysMask0 ... MTRRphysMask7 */
+ case 0x200 ... 0x20f:
if (ECX & 1)
msr.mtrr_physmask[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
else
msr.mtrr_physbase[(ECX - 0x200) >> 1] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix64K_00000 */
case 0x250:
msr.mtrr_fix64k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_80000 */
case 0x258:
msr.mtrr_fix16k_8000 = EAX | ((uint64_t) EDX << 32);
break;
+ /* MTRRfix16K_A0000 */
case 0x259:
msr.mtrr_fix16k_a000 = EAX | ((uint64_t) EDX << 32);
break;
- case 0x268:
- case 0x269:
- case 0x26a:
- case 0x26b:
- case 0x26c:
- case 0x26d:
- case 0x26e:
- case 0x26f:
+ /* MTRRfix4K_C0000 ... MTRRfix4K_F8000 */
+ case 0x268 ... 0x26f:
msr.mtrr_fix4k[ECX - 0x268] = EAX | ((uint64_t) EDX << 32);
break;
+ /* Page Attribute Table */
case 0x277:
+ if (cpu_s->cpu_type < CPU_PENTIUM2D)
+ goto i686_invalid_wrmsr;
msr.pat = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown */
+ case 0x280:
+ if (cpu_s->cpu_type == CPU_PENTIUMPRO)
+ goto i686_invalid_wrmsr;
+ break;
+ /* MTRRdefType */
case 0x2ff:
msr.mtrr_deftype = EAX | ((uint64_t) EDX << 32);
break;
+ /* MC0_CTL - Machine Check 0 Control */
case 0x400:
+ /* MC1_CTL - Machine Check 1 Control */
case 0x404:
+ /* MC2_CTL - Machine Check 2 Control */
case 0x408:
+ /* MC4_CTL - Machine Check 4 Control */
case 0x40c:
+ /* MC3_CTL - Machine Check 3 Control */
case 0x410:
msr.mca_ctl[(ECX - 0x400) >> 2] = EAX | ((uint64_t) EDX << 32);
break;
+ /* MC0_STATUS - Machine Check 0 Status */
case 0x401:
+ /* MC0_ADDR - Machine Check 0 Address */
case 0x402:
+ /* MC1_STATUS - Machine Check 1 Status */
case 0x405:
+ /* MC1_ADDR - Machine Check 1 Address */
case 0x406:
- case 0x407:
+ /* MC2_STATUS - Machine Check 2 Status */
case 0x409:
+ /* MC2_ADDR - Machine Check 2 Address */
+ case 0x40a:
+ /* MC4_STATUS - Machine Check 4 Status */
case 0x40d:
+ /* MC4_ADDR - Machine Check 4 Address */
case 0x40e:
+ /* MC3_STATUS - Machine Check 3 Status */
case 0x411:
+ /* MC3_ADDR - Machine Check 3 Address */
case 0x412:
if (EAX || EDX)
x86gpf(NULL, 0);
break;
+ /* Unknown */
case 0x570:
msr.ecx570 = EAX | ((uint64_t) EDX << 32);
break;
+ /* Unknown, possibly debug registers? */
+ case 0x1000 ... 0x1007:
+ /* Unknown, possibly control registers? */
+ case 0x2000:
+ case 0x2002 ... 0x2004:
+ break;
default:
i686_invalid_wrmsr:
cpu_log("WRMSR: Invalid MSR: %08X\n", ECX);
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index b547fb99f5..9b154cd0d9 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -21,8 +21,6 @@
#ifndef EMU_CPU_H
#define EMU_CPU_H
-#include "softfloat/softfloat.h"
-
enum {
FPU_NONE,
FPU_8087,
@@ -86,42 +84,33 @@ enum {
};
enum {
- CPU_PKG_8088 = (1 << 0),
- CPU_PKG_8088_EUROPC = (1 << 1),
- CPU_PKG_8086 = (1 << 2),
- CPU_PKG_188 = (1 << 3),
- CPU_PKG_186 = (1 << 4),
- CPU_PKG_286 = (1 << 5),
- CPU_PKG_386SX = (1 << 6),
- CPU_PKG_386DX = (1 << 7),
- CPU_PKG_M6117 = (1 << 8),
- CPU_PKG_386SLC_IBM = (1 << 9),
- CPU_PKG_486SLC = (1 << 10),
- CPU_PKG_486SLC_IBM = (1 << 11),
- CPU_PKG_486BL = (1 << 12),
- CPU_PKG_486DLC = (1 << 13),
- CPU_PKG_SOCKET1 = (1 << 14),
- CPU_PKG_SOCKET3 = (1 << 15),
- CPU_PKG_SOCKET3_PC330 = (1 << 16),
- CPU_PKG_STPC = (1 << 17),
- CPU_PKG_SOCKET4 = (1 << 18),
- CPU_PKG_SOCKET5_7 = (1 << 19),
- CPU_PKG_SOCKET8 = (1 << 20),
- CPU_PKG_SLOT1 = (1 << 21),
- CPU_PKG_SLOT2 = (1 << 22),
- CPU_PKG_SLOTA = (1 << 23),
- CPU_PKG_SOCKET370 = (1 << 24),
- CPU_PKG_SOCKETA = (1 << 25),
- CPU_PKG_EBGA368 = (1 << 26)
+ CPU_PKG_8088 = (1 << 0),
+ CPU_PKG_8088_EUROPC = (1 << 1),
+ CPU_PKG_8086 = (1 << 2),
+ CPU_PKG_188 = (1 << 3),
+ CPU_PKG_186 = (1 << 4),
+ CPU_PKG_286 = (1 << 5),
+ CPU_PKG_386SX = (1 << 6),
+ CPU_PKG_386DX = (1 << 7),
+ CPU_PKG_386DX_DESKPRO386 = (1 << 8),
+ CPU_PKG_M6117 = (1 << 9),
+ CPU_PKG_386SLC_IBM = (1 << 10),
+ CPU_PKG_486SLC = (1 << 11),
+ CPU_PKG_486SLC_IBM = (1 << 12),
+ CPU_PKG_486BL = (1 << 13),
+ CPU_PKG_486DLC = (1 << 14),
+ CPU_PKG_SOCKET1 = (1 << 15),
+ CPU_PKG_SOCKET3 = (1 << 16),
+ CPU_PKG_SOCKET3_PC330 = (1 << 17),
+ CPU_PKG_STPC = (1 << 18),
+ CPU_PKG_SOCKET4 = (1 << 19),
+ CPU_PKG_SOCKET5_7 = (1 << 20),
+ CPU_PKG_SOCKET8 = (1 << 21),
+ CPU_PKG_SLOT1 = (1 << 22),
+ CPU_PKG_SLOT2 = (1 << 23),
+ CPU_PKG_SOCKET370 = (1 << 24)
};
-#define MANU_INTEL 0
-#define MANU_AMD 1
-#define MANU_CYRIX 2
-#define MANU_IDT 3
-#define MANU_NEC 4
-#define MANU_IBM 5
-
#define CPU_SUPPORTS_DYNAREC 1
#define CPU_REQUIRES_DYNAREC 2
#define CPU_ALTERNATE_XTAL 4
@@ -165,17 +154,6 @@ typedef struct {
const CPU *cpus;
} cpu_family_t;
-typedef struct {
- const char *family;
- const uint32_t rspeed;
- const double multi;
-} cpu_legacy_table_t;
-
-typedef struct {
- const char *machine;
- const cpu_legacy_table_t **tables;
-} cpu_legacy_machine_t;
-
#define C_FLAG 0x0001
#define P_FLAG 0x0004
#define A_FLAG 0x0010
@@ -194,6 +172,7 @@ typedef struct {
#define VIP_FLAG 0x0010 /* in EFLAGS */
#define VID_FLAG 0x0020 /* in EFLAGS */
+#define EM_FLAG 0x00004 /* in CR0 */
#define WP_FLAG 0x10000 /* in CR0 */
#define CR4_VME (1 << 0) /* Virtual 8086 Mode Extensions */
@@ -246,101 +225,97 @@ typedef union {
} MMX_REG;
typedef struct {
- /* IDT WinChip and WinChip 2 MSR's */
- uint32_t tr1; /* 0x00000002, 0x0000000e */
- uint32_t tr12; /* 0x00000002, 0x0000000e */
- uint32_t cesr; /* 0x00000011 */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */
-
- /* Weird long MSR's used by the Hyper-V BIOS. */
- uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits
- like a real Deschutes does. */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t ecx79; /* 0x00000079 */
-
- /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t ecx83; /* 0x00000083 - AMD K5 and K6 MSR's. */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t ecx8x[4]; /* 0x00000088 - 0x0000008b */
- uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */
- uint64_t mtrr_cap; /* 0x000000fe */
-
- /* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III */
- uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
- uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */
- uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t ecx116; /* 0x00000116 */
- uint64_t ecx11x[4]; /* 0x00000118 - 0x0000011b */
- uint64_t ecx11e; /* 0x0000011e */
-
- /* Pentium II Klamath and Pentium II Deschutes MSR's */
- uint16_t sysenter_cs; /* 0x00000174 - SYSENTER/SYSEXIT MSR's */
- uint32_t sysenter_esp; /* 0x00000175 - SYSENTER/SYSEXIT MSR's */
- uint32_t sysenter_eip; /* 0x00000176 - SYSENTER/SYSEXIT MSR's */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */
- uint64_t ecx186; /* 0x00000186, 0x00000187 */
- uint64_t ecx187; /* 0x00000186, 0x00000187 */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */
- uint64_t ecx1e0; /* 0x000001e0 */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
- on the VIA Cyrix III */
- uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */
+ /* IBM 386SLC/486SLC/486BL MSRs */
+ uint64_t ibm_por; /* 0x00001000 - 386SLC and later */
+ uint64_t ibm_crcr; /* 0x00001001 - 386SLC and later */
+ uint64_t ibm_por2; /* 0x00001002 - 486SLC and later */
+ uint64_t ibm_pcr; /* 0x00001004 - 486BL3 */
+
+ /* IDT WinChip C6/2/VIA Cyrix III MSRs */
+ uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
+ uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */
+ uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
+ uint64_t mcr[8]; /* 0x00000110 - 0x00000117 (IDT) */
+ uint32_t mcr_ctrl; /* 0x00000120 (IDT) */
+
+ /* AMD K5/K6 MSRs */
+ uint64_t amd_aar; /* 0x00000082 - all K5 */
+ uint64_t amd_hwcr; /* 0x00000083 - all K5 and all K6 */
+ uint64_t amd_watmcr; /* 0x00000085 - K5 Model 1 and later */
+ uint64_t amd_wapmrr; /* 0x00000086 - K5 Model 1 and later */
+
+ uint64_t amd_efer; /* 0xc0000080 - all K5 and all K6 */
+ uint64_t amd_star; /* 0xc0000081 - K6-2 and later */
+ uint64_t amd_whcr; /* 0xc0000082 - all K5 and all K6 */
+ uint64_t amd_uwccr; /* 0xc0000085 - K6-2C and later */
+ uint64_t amd_epmr; /* 0xc0000086 - K6-III+/2+ only */
+ uint64_t amd_psor; /* 0xc0000087 - K6-2C and later */
+ uint64_t amd_pfir; /* 0xc0000088 - K6-2C and later */
+ uint64_t amd_l2aar; /* 0xc0000089 - K6-III and later */
+
+ /* Pentium/Pentium MMX MSRs */
+ uint64_t mcar; /* 0x00000000 - also on K5 and (R/W) K6 */
+ uint64_t mctr; /* 0x00000001 - also on K5 and (R/W) K6 */
+ uint32_t tr1; /* 0x00000002 - also on WinChip C6/2 */
+ uint32_t tr2; /* 0x00000004 - reserved on PMMX */
+ uint32_t tr3; /* 0x00000005 */
+ uint32_t tr4; /* 0x00000006 */
+ uint32_t tr5; /* 0x00000007 */
+ uint32_t tr6; /* 0x00000008 */
+ uint32_t tr7; /* 0x00000009 */
+ uint32_t tr9; /* 0x0000000b */
+ uint32_t tr10; /* 0x0000000c */
+ uint32_t tr11; /* 0x0000000d */
+ uint32_t tr12; /* 0x0000000e - also on WinChip C6/2 and K6 */
+ uint32_t cesr; /* 0x00000011 - also on WinChip C6/2 and Cx6x86MX */
+ uint64_t pmc[2]; /* 0x00000012, 0x00000013 - also on WinChip C6/2 and Cx6x86MX */
+ uint32_t fp_last_xcpt; /* 0x8000001b - undocumented */
+ uint32_t probe_ctl; /* 0x8000001d - undocumented */
+ uint32_t ecx8000001e; /* 0x8000001e - undocumented */
+ uint32_t ecx8000001f; /* 0x8000001f - undocumented */
+
+ /* Pentium Pro/II MSRs */
+ uint64_t apic_base; /* 0x0000001b */
+ uint32_t test_ctl; /* 0x00000033 */
+ uint64_t bios_updt; /* 0x00000079 */
+
+ uint64_t bbl_cr_dx[4]; /* 0x00000088 - 0x0000008b */
+ uint64_t perfctr[2]; /* 0x000000c1, 0x000000c2 */
+ uint64_t mtrr_cap; /* 0x000000fe */
+
+ uint64_t bbl_cr_addr; /* 0x00000116 */
+ uint64_t bbl_cr_decc; /* 0x00000118 */
+ uint64_t bbl_cr_ctl; /* 0x00000119 */
+ uint64_t bbl_cr_trig; /* 0x0000011a */
+ uint64_t bbl_cr_busy; /* 0x0000011b */
+ uint64_t bbl_cr_ctl3; /* 0x0000011e */
+
+ uint16_t sysenter_cs; /* 0x00000174 - Pentium II and later */
+ uint32_t sysenter_esp; /* 0x00000175 - Pentium II and later */
+ uint32_t sysenter_eip; /* 0x00000176 - Pentium II and later */
+
+ uint64_t mcg_ctl; /* 0x0000017b */
+ uint64_t evntsel[2]; /* 0x00000186, 0x00000187 */
+
+ uint32_t debug_ctl; /* 0x000001d9 */
+ uint32_t rob_cr_bkuptmpdr6; /* 0x000001e0 */
+
+ /* MTTR-related MSRs also present on the VIA Cyrix III */
+ uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f (ECX & 0) */
uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */
uint64_t mtrr_fix64k_8000; /* 0x00000250 */
uint64_t mtrr_fix16k_8000; /* 0x00000258 */
uint64_t mtrr_fix16k_a000; /* 0x00000259 */
uint64_t mtrr_fix4k[8]; /* 0x00000268 - 0x0000026f */
+ uint64_t mtrr_deftype; /* 0x000002ff */
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t pat; /* 0x00000277 */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
- on the VIA Cyrix III */
- uint64_t mtrr_deftype; /* 0x000002ff */
-
- /* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
- uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */
+ uint64_t pat; /* 0x00000277 - Pentium II Deschutes and later */
+ uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 */
uint64_t ecx570; /* 0x00000570 */
- /* IBM 386SLC, 486SLC, and 486BL MSR's */
- uint64_t ibm_por; /* 0x00001000 - Processor Operation Register */
- uint64_t ibm_crcr; /* 0x00001001 - Cache Region Control Register */
-
- /* IBM 486SLC and 486BL MSR's */
- uint64_t ibm_por2; /* 0x00001002 - Processor Operation Register */
-
- /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_efer; /* 0xc0000080 */
-
- /* AMD K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t star; /* 0xc0000081 */
-
- /* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_whcr; /* 0xc0000082 */
-
- /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_uwccr; /* 0xc0000085 */
-
- /* AMD K6-2P and K6-3P MSR's */
- uint64_t amd_epmr; /* 0xc0000086 */
-
- /* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_psor; /* 0xc0000087, 0xc0000088 */
- uint64_t amd_pfir; /* 0xc0000087, 0xc0000088 */
-
- /* K6-3, K6-2P, and K6-3P MSR's */
- uint64_t amd_l2aar; /* 0xc0000089 */
+ /* Other/Unclassified MSRs */
+ uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits
+ like a real Deschutes does. */
} msr_t;
typedef struct {
@@ -429,22 +404,6 @@ typedef struct {
uint32_t _smbase;
} cpu_state_t;
-typedef struct {
- uint16_t cwd;
- uint16_t swd;
- uint16_t tag;
- uint16_t foo;
- uint32_t fip;
- uint32_t fdp;
- uint16_t fcs;
- uint16_t fds;
- floatx80 st_space[8];
- unsigned char tos;
- unsigned char align1;
- unsigned char align2;
- unsigned char align3;
-} fpu_state_t;
-
#define in_smm cpu_state._in_smm
#define smi_line cpu_state._smi_line
@@ -525,10 +484,8 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state_t) <= 128)
/* Global variables. */
extern cpu_state_t cpu_state;
-extern fpu_state_t fpu_state;
extern const cpu_family_t cpu_families[];
-extern const cpu_legacy_machine_t cpu_legacy_table[];
extern cpu_family_t *cpu_f;
extern CPU *cpu_s;
extern int cpu_override;
@@ -607,7 +564,6 @@ extern double bus_timing;
extern double isa_timing;
extern double pci_timing;
extern double agp_timing;
-extern uint64_t pmc[2];
extern uint16_t temp_seg_data[4];
extern uint16_t cs_msr;
extern uint32_t esp_msr;
@@ -617,8 +573,6 @@ extern uint32_t eip_msr;
extern uint64_t amd_efer;
extern uint64_t star;
-#define FPU_CW_Reserved_Bits (0xe0c0)
-
#define cr0 cpu_state.CR0.l
#define msw cpu_state.CR0.w
extern uint32_t cr2;
@@ -788,6 +742,11 @@ void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg);
#define SMHR_VALID (1 << 0)
#define SMHR_ADDR_MASK (0xfffffffc)
+typedef union {
+ uint32_t fd;
+ uint8_t b[4];
+} fetch_dat_t;
+
typedef struct {
struct {
uint32_t base;
@@ -842,4 +801,16 @@ extern void prefetch_flush(void);
extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32);
+extern int lock_legal[256];
+extern int lock_legal_0f[256];
+extern int lock_legal_ba[8];
+extern int lock_legal_80[8];
+extern int lock_legal_f6[8];
+extern int lock_legal_fe[8];
+
+extern int in_lock;
+extern int cpu_override_interpreter;
+
+extern int is_lock_legal(uint32_t fetchdat);
+
#endif /*EMU_CPU_H*/
diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c
index fe55a4f232..502b2c86e3 100644
--- a/src/cpu/cpu_table.c
+++ b/src/cpu/cpu_table.c
@@ -1043,6 +1043,17 @@ const cpu_family_t cpu_families[] = {
{"", 0}
}
}, {
+ .package = CPU_PKG_386DX_DESKPRO386,
+ .manufacturer = "Intel",
+ .name = "i386DX",
+ .internal_name = "i386dx_deskpro386",
+ .cpus = (const CPU[]) {
+ {"16", CPU_386DX, fpus_80286, 16000000, 1, 5000, 0x0308, 0, 0, 0, 3,3,3,3, 2},
+ {"20", CPU_386DX, fpus_80386, 20000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3},
+ {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3},
+ {"", 0}
+ }
+ }, {
.package = CPU_PKG_386DX,
.manufacturer = "Intel",
.name = "RapidCAD",
@@ -1387,9 +1398,9 @@ const cpu_family_t cpu_families[] = {
.name = "Am5x86",
.internal_name = "am5x86",
.cpus = (const CPU[]) {
- {"P75", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
- {"P75+", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
- {"P90", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
+ {"133 (P75)", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
+ {"150 (P75+)", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
+ {"160 (P90)", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
{"", 0}
}
}, {
@@ -1604,28 +1615,25 @@ const cpu_family_t cpu_families[] = {
{
.package = CPU_PKG_SOCKET5_7,
.manufacturer = "AMD",
- .name = "K5 (5k86)",
- .internal_name = "k5_5k86",
+ .name = "K5 (Model 0)",
+ .internal_name = "k5_ssa5",
.cpus = (const CPU[]) {
- {"75 (P75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
- {"90 (P90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
- {"100 (P100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
- {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
- {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
- {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
- {"116.5 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
- {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
+ {"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
+ {"90 (PR90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
+ {"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"", 0}
}
}, {
.package = CPU_PKG_SOCKET5_7,
.manufacturer = "AMD",
- .name = "K5 (SSA/5)",
- .internal_name = "k5_ssa5",
+ .name = "K5 (Model 1/2/3)",
+ .internal_name = "k5_5k86",
.cpus = (const CPU[]) {
- {"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
- {"90 (PR90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
- {"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
+ {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
+ {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
+ {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
+ {"116.7 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
+ {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
{"", 0}
}
},
@@ -1763,12 +1771,12 @@ const cpu_family_t cpu_families[] = {
.name = "Cx6x86",
.internal_name = "cx6x86",
.cpus = (const CPU[]) {
- {"P90", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
- {"PR120+", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
- {"PR133+", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
- {"PR150+", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
- {"PR166+", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
- {"PR200+", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
+ {"80 (PR90+)", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
+ {"100 (PR120+)", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
+ {"110 (PR133+)", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
+ {"120 (PR150+)", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
+ {"133 (PR166+)", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
+ {"150 (PR200+)", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
{"", 0}
}
}, {
@@ -1777,10 +1785,10 @@ const cpu_family_t cpu_families[] = {
.name = "Cx6x86L",
.internal_name = "cx6x86l",
.cpus = (const CPU[]) {
- {"PR133+", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
- {"PR150+", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
- {"PR166+", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
- {"PR200+", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
+ {"110 (PR133+)", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
+ {"120 (PR150+)", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
+ {"133 (PR166+)", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
+ {"150 (PR200+)", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
{"", 0}
}
}, {
@@ -1789,10 +1797,10 @@ const cpu_family_t cpu_families[] = {
.name = "Cx6x86MX",
.internal_name = "cx6x86mx",
.cpus = (const CPU[]) {
- {"PR166", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
- {"PR200", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
- {"PR233", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
- {"PR266", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
+ {"133 (PR166)", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
+ {"166 (PR200)", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
+ {"187.5 (PR233)", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
+ {"208.3 (PR266)", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"", 0}
}
}, {
@@ -1801,11 +1809,11 @@ const cpu_family_t cpu_families[] = {
.name = "MII",
.internal_name = "mii",
.cpus = (const CPU[]) {
- {"PR300", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
- {"PR333", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
- {"PR366", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
- {"PR400", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
- {"PR433", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
+ {"233 (PR300)", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
+ {"250/83 (PR333)", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
+ {"250/100 (PR366)", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
+ {"285 (PR400)", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
+ {"300 (PR433)", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
{"", 0}
}
},
@@ -1972,957 +1980,3 @@ const cpu_family_t cpu_families[] = {
}
// clang-format on
};
-
-/* Legacy CPU tables for backwards compatibility. */
-
-static const cpu_legacy_table_t cpus_8088[] = {
- {"8088", 4772728, 1},
- { "8088", 7159092, 1},
- { "8088", 8000000, 1},
- { "8088", 10000000, 1},
- { "8088", 12000000, 1},
- { "8088", 16000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_pcjr[] = {
- {"8088", 4772728, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_europc[] = {
- {"8088_europc", 4772728, 1},
- { "8088_europc", 7159092, 1},
- { "8088_europc", 9545456, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_8086[] = {
- {"8086", 7159092, 1},
- { "8086", 8000000, 1},
- { "8086", 9545456, 1},
- { "8086", 10000000, 1},
- { "8086", 12000000, 1},
- { "8086", 16000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_pc1512[] = {
- {"8086", 8000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_286[] = {
- {"286", 6000000, 1},
- { "286", 8000000, 1},
- { "286", 10000000, 1},
- { "286", 12500000, 1},
- { "286", 16000000, 1},
- { "286", 20000000, 1},
- { "286", 25000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_ibmat[] = {
- {"286", 6000000, 1},
- { "286", 8000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_ibmxt286[] = {
- {"286", 6000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_ps1_m2011[] = {
- {"286", 10000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_ps2_m30_286[] = {
- {"286", 10000000, 1},
- { "286", 12500000, 1},
- { "286", 16000000, 1},
- { "286", 20000000, 1},
- { "286", 25000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_i386SX[] = {
- {"i386sx", 16000000, 1},
- { "i386sx", 20000000, 1},
- { "i386sx", 25000000, 1},
- { "i386sx", 33333333, 1},
- { "i386sx", 40000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_i386DX[] = {
- {"i386dx", 16000000, 1},
- { "i386dx", 20000000, 1},
- { "i386dx", 25000000, 1},
- { "i386dx", 33333333, 1},
- { "i386dx", 40000000, 1},
- { "rapidcad", 25000000, 1},
- { "rapidcad", 33333333, 1},
- { "rapidcad", 40000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_Am386SX[] = {
- {"am386sx", 16000000, 1},
- { "am386sx", 20000000, 1},
- { "am386sx", 25000000, 1},
- { "am386sx", 33333333, 1},
- { "am386sx", 40000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_Am386DX[] = {
- {"am386dx", 25000000, 1},
- { "am386dx", 33333333, 1},
- { "am386dx", 40000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_ALiM6117[] = {
- {"m6117", 33333333, 1},
- { "m6117", 40000000, 1},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_486SLC[] = {
- {"cx486slc", 20000000, 1},
- { "cx486slc", 25000000, 1},
- { "cx486slc", 33333333, 1},
- { "cx486srx2", 32000000, 2},
- { "cx486srx2", 40000000, 2},
- { "cx486srx2", 50000000, 2},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_IBM486SLC[] = {
- {"ibm486slc", 33333333, 1},
- { "ibm486slc2", 40000000, 2},
- { "ibm486slc2", 50000000, 2},
- { "ibm486slc2", 66666666, 2},
- { "ibm486slc3", 60000000, 3},
- { "ibm486slc3", 75000000, 3},
- { "ibm486slc3", 100000000, 3},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_IBM486BL[] = {
- {"ibm486bl2", 50000000, 2},
- { "ibm486bl2", 66666666, 2},
- { "ibm486bl3", 75000000, 3},
- { "ibm486bl3", 100000000, 3},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_486DLC[] = {
- {"cx486dlc", 25000000, 1},
- { "cx486dlc", 33333333, 1},
- { "cx486dlc", 40000000, 1},
- { "cx486drx2", 32000000, 2},
- { "cx486drx2", 40000000, 2},
- { "cx486drx2", 50000000, 2},
- { "cx486drx2", 66666666, 2},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_i486S1[] = {
- {"i486sx", 16000000, 1},
- { "i486sx", 20000000, 1},
- { "i486sx", 25000000, 1},
- { "i486sx", 33333333, 1},
- { "i486sx2", 50000000, 2},
- { "i486sx2", 66666666, 2},
- { "i486dx", 25000000, 1},
- { "i486dx", 33333333, 1},
- { "i486dx", 50000000, 1},
- { "i486dx2", 40000000, 2},
- { "i486dx2", 50000000, 2},
- { "i486dx2", 66666666, 2},
- { "idx4_od", 75000000, 3},
- { "idx4_od", 100000000, 3},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_Am486S1[] = {
- {"am486sx", 33333333, 1},
- { "am486sx", 40000000, 1},
- { "am486sx2", 50000000, 2},
- { "am486sx2", 66666666, 2},
- { "am486dx", 33333333, 1},
- { "am486dx", 40000000, 1},
- { "am486dx2", 50000000, 2},
- { "am486dx2", 66666666, 2},
- { "am486dx2", 80000000, 2},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_Cx486S1[] = {
- {"cx486s", 25000000, 1.0},
- { "cx486s", 33333333, 1.0},
- { "cx486s", 40000000, 1.0},
- { "cx486dx", 33333333, 1.0},
- { "cx486dx", 40000000, 1.0},
- { "cx486dx2", 50000000, 2.0},
- { "cx486dx2", 66666666, 2.0},
- { "cx486dx2", 80000000, 2.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_i486[] = {
- {"i486sx", 16000000, 1.0},
- { "i486sx", 20000000, 1.0},
- { "i486sx", 25000000, 1.0},
- { "i486sx", 33333333, 1.0},
- { "i486sx2", 50000000, 2.0},
- { "i486sx2", 66666666, 2.0},
- { "i486dx", 25000000, 1.0},
- { "i486dx", 33333333, 1.0},
- { "i486dx", 50000000, 1.0},
- { "i486dx2", 40000000, 2.0},
- { "i486dx2", 50000000, 2.0},
- { "i486dx2", 66666666, 2.0},
- { "idx4", 75000000, 3.0},
- { "idx4", 100000000, 3.0},
- { "idx4_od", 75000000, 3.0},
- { "idx4_od", 100000000, 3.0},
- { "pentium_p24t", 62500000, 2.5},
- { "pentium_p24t", 83333333, 2.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_i486_PC330[] = {
- {"i486dx2", 50000000, 2.0},
- { "i486dx2", 66666666, 2.0},
- { "idx4", 75000000, 3.0},
- { "idx4", 100000000, 3.0},
- { "pentium_p24t", 62500000, 2.5},
- { "pentium_p24t", 83333333, 2.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Am486[] = {
- {"am486sx", 33333333, 1.0},
- { "am486sx", 40000000, 1.0},
- { "am486sx2", 50000000, 2.0},
- { "am486sx2", 66666666, 2.0},
- { "am486dx", 33333333, 1.0},
- { "am486dx", 40000000, 1.0},
- { "am486dx2", 50000000, 2.0},
- { "am486dx2", 66666666, 2.0},
- { "am486dx2", 80000000, 2.0},
- { "am486dx4", 75000000, 3.0},
- { "am486dx4", 90000000, 3.0},
- { "am486dx4", 100000000, 3.0},
- { "am486dx4", 120000000, 3.0},
- { "am5x86", 133333333, 4.0},
- { "am5x86", 150000000, 3.0},
- { "am5x86", 160000000, 4.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Cx486[] = {
- {"cx486s", 25000000, 1.0},
- { "cx486s", 33333333, 1.0},
- { "cx486s", 40000000, 1.0},
- { "cx486dx", 33333333, 1.0},
- { "cx486dx", 40000000, 1.0},
- { "cx486dx2", 50000000, 2.0},
- { "cx486dx2", 66666666, 2.0},
- { "cx486dx2", 80000000, 2.0},
- { "cx486dx4", 75000000, 3.0},
- { "cx486dx4", 100000000, 3.0},
- { "cx5x86", 80000000, 2.0},
- { "cx5x86", 100000000, 3.0},
- { "cx5x86", 120000000, 3.0},
- { "cx5x86", 133333333, 4.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_STPCDX[] = {
- {"stpc_dx", 66666666, 1.0},
- { "stpc_dx", 75000000, 1.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_STPCDX2[] = {
- {"stpc_dx2", 133333333, 2.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_6x863V[] = {
- {"cx6x86", 80000000, 2.0},
- { "cx6x86", 100000000, 2.0},
- { "cx6x86", 110000000, 2.0},
- { "cx6x86", 120000000, 2.0},
- { "cx6x86", 133333333, 2.0},
- { "cx6x86", 150000000, 2.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_6x86[] = {
- {"cx6x86", 80000000, 2.0},
- { "cx6x86", 100000000, 2.0},
- { "cx6x86", 110000000, 2.0},
- { "cx6x86", 120000000, 2.0},
- { "cx6x86", 133333333, 2.0},
- { "cx6x86", 150000000, 2.0},
- { "cx6x86l", 110000000, 2.0},
- { "cx6x86l", 120000000, 2.0},
- { "cx6x86l", 133333333, 2.0},
- { "cx6x86l", 150000000, 2.0},
- { "cx6x86mx", 133333333, 2.0},
- { "cx6x86mx", 166666666, 2.5},
- { "cx6x86mx", 187500000, 2.5},
- { "cx6x86mx", 208333333, 2.5},
- { "mii", 233333333, 3.5},
- { "mii", 250000000, 3.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_6x86SS7[] = {
- {"cx6x86", 80000000, 2.0},
- { "cx6x86", 100000000, 2.0},
- { "cx6x86", 110000000, 2.0},
- { "cx6x86", 120000000, 2.0},
- { "cx6x86", 133333333, 2.0},
- { "cx6x86", 150000000, 2.0},
- { "cx6x86l", 110000000, 2.0},
- { "cx6x86l", 120000000, 2.0},
- { "cx6x86l", 133333333, 2.0},
- { "cx6x86l", 150000000, 2.0},
- { "cx6x86mx", 133333333, 2.0},
- { "cx6x86mx", 166666666, 2.5},
- { "cx6x86mx", 187500000, 2.5},
- { "cx6x86mx", 208333333, 2.5},
- { "mii", 233333333, 3.5},
- { "mii", 250000000, 3.0},
- { "mii", 250000000, 2.5},
- { "mii", 285000000, 3.0},
- { "mii", 300000000, 3.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_WinChip[] = {
- {"winchip", 75000000, 1.5},
- { "winchip", 90000000, 1.5},
- { "winchip", 100000000, 1.5},
- { "winchip", 120000000, 2.0},
- { "winchip", 133333333, 2.0},
- { "winchip", 150000000, 2.5},
- { "winchip", 166666666, 2.5},
- { "winchip", 180000000, 3.0},
- { "winchip", 200000000, 3.0},
- { "winchip", 225000000, 3.0},
- { "winchip", 240000000, 4.0},
- { "winchip2", 200000000, 3.0},
- { "winchip2", 225000000, 3.0},
- { "winchip2", 240000000, 4.0},
- { "winchip2", 250000000, 3.0},
- { "winchip2a", 200000000, 3.0},
- { "winchip2a", 233333333, 3.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_WinChip_SS7[] = {
- {"winchip", 75000000, 1.5},
- { "winchip", 90000000, 1.5},
- { "winchip", 100000000, 1.5},
- { "winchip", 120000000, 2.0},
- { "winchip", 133333333, 2.0},
- { "winchip", 150000000, 2.5},
- { "winchip", 166666666, 2.5},
- { "winchip", 180000000, 3.0},
- { "winchip", 200000000, 3.0},
- { "winchip", 225000000, 3.0},
- { "winchip", 240000000, 4.0},
- { "winchip2", 200000000, 3.0},
- { "winchip2", 225000000, 3.0},
- { "winchip2", 240000000, 4.0},
- { "winchip2", 250000000, 3.0},
- { "winchip2a", 200000000, 3.0},
- { "winchip2a", 233333333, 3.5},
- { "winchip2a", 233333333, 7.0},
- { "winchip2a", 250000000, 2.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Pentium5V[] = {
- {"pentium_p5", 60000000, 1},
- { "pentium_p5", 66666666, 1},
- { "pentium_p54c_od5v", 120000000, 2},
- { "pentium_p54c_od5v", 133333333, 2},
- { NULL, 0, 0}
-};
-
-static const cpu_legacy_table_t cpus_PentiumS5[] = {
- {"pentium_p54c", 75000000, 1.5},
- { "pentium_p55c_od", 75000000, 1.5},
- { "pentium_p54c", 90000000, 1.5},
- { "pentium_p54c", 100000000, 2.0},
- { "pentium_p54c", 100000000, 1.5},
- { "pentium_p54c", 120000000, 2.0},
- { "pentium_p54c", 133333333, 2.0},
- { "pentium_p54c_od3v", 125000000, 3.0},
- { "pentium_p54c_od3v", 150000000, 2.5},
- { "pentium_p54c_od3v", 166666666, 2.5},
- { "pentium_p55c_od", 125000000, 2.5},
- { "pentium_p55c_od", 150000000, 2.5},
- { "pentium_p55c_od", 166000000, 2.5},
- { "pentium_p55c_od", 180000000, 3.0},
- { "pentium_p55c_od", 200000000, 3.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Pentium3V[] = {
- {"pentium_p54c", 75000000, 1.5},
- { "pentium_p55c_od", 75000000, 1.5},
- { "pentium_p54c", 90000000, 1.5},
- { "pentium_p54c", 100000000, 2.0},
- { "pentium_p54c", 100000000, 1.5},
- { "pentium_p54c", 120000000, 2.0},
- { "pentium_p54c", 133333333, 2.0},
- { "pentium_p54c", 150000000, 2.5},
- { "pentium_p54c", 166666666, 2.5},
- { "pentium_p54c", 200000000, 3.0},
- { "pentium_p54c_od3v", 125000000, 2.5},
- { "pentium_p54c_od3v", 150000000, 2.5},
- { "pentium_p54c_od3v", 166666666, 2.5},
- { "pentium_p55c_od", 125000000, 2.5},
- { "pentium_p55c_od", 150000000, 2.5},
- { "pentium_p55c_od", 166000000, 2.5},
- { "pentium_p55c_od", 180000000, 3.0},
- { "pentium_p55c_od", 200000000, 3.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Pentium[] = {
- {"pentium_p54c", 75000000, 1.5},
- { "pentium_p55c_od", 75000000, 1.5},
- { "pentium_p54c", 90000000, 1.5},
- { "pentium_p54c", 100000000, 2.0},
- { "pentium_p54c", 100000000, 1.5},
- { "pentium_p54c", 120000000, 2.0},
- { "pentium_p54c", 133333333, 2.0},
- { "pentium_p54c", 150000000, 2.5},
- { "pentium_p54c", 166666666, 2.5},
- { "pentium_p54c", 200000000, 3.0},
- { "pentium_p55c", 166666666, 2.5},
- { "pentium_p55c", 200000000, 3.0},
- { "pentium_p55c", 233333333, 3.5},
- { "pentium_tillamook", 120000000, 2.0},
- { "pentium_tillamook", 133333333, 2.0},
- { "pentium_tillamook", 150000000, 2.5},
- { "pentium_tillamook", 166666666, 2.5},
- { "pentium_tillamook", 200000000, 3.0},
- { "pentium_tillamook", 233333333, 3.5},
- { "pentium_tillamook", 266666666, 4.0},
- { "pentium_tillamook", 300000000, 4.5},
- { "pentium_p54c_od3v", 125000000, 2.5},
- { "pentium_p54c_od3v", 150000000, 2.5},
- { "pentium_p54c_od3v", 166666666, 2.5},
- { "pentium_p55c_od", 125000000, 2.5},
- { "pentium_p55c_od", 150000000, 2.5},
- { "pentium_p55c_od", 166000000, 2.5},
- { "pentium_p55c_od", 180000000, 3.0},
- { "pentium_p55c_od", 200000000, 3.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_K5[] = {
- {"k5_5k86", 75000000, 1.5},
- { "k5_ssa5", 75000000, 1.5},
- { "k5_5k86", 90000000, 1.5},
- { "k5_ssa5", 90000000, 1.5},
- { "k5_5k86", 100000000, 1.5},
- { "k5_ssa5", 100000000, 1.5},
- { "k5_5k86", 120000000, 2.0},
- { "k5_5k86", 133333333, 2.0},
- { "k5_5k86", 150000000, 2.5},
- { "k5_5k86", 166666666, 2.5},
- { "k5_5k86", 200000000, 3.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_K56[] = {
- {"k6_m6", 66666666, 1.0},
- { "k6_m6", 100000000, 1.5},
- { "k6_m6", 133333333, 2.0},
- { "k6_m6", 166666666, 2.5},
- { "k6_m6", 200000000, 3.0},
- { "k6_m6", 233333333, 3.5},
- { "k6_m7", 100000000, 1.5},
- { "k6_m7", 133333333, 2.0},
- { "k6_m7", 166666666, 2.5},
- { "k6_m7", 200000000, 3.0},
- { "k6_m7", 233333333, 3.5},
- { "k6_m7", 266666666, 4.0},
- { "k6_m7", 300000000, 4.5},
- { "k6_2", 100000000, 1.5},
- { "k6_2", 133333333, 2.0},
- { "k6_2", 166666666, 2.5},
- { "k6_2", 200000000, 3.0},
- { "k6_2", 233333333, 3.5},
- { "k6_2", 266666666, 4.0},
- { "k6_2", 300000000, 4.5},
- { "k6_2", 366666666, 5.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_K56_SS7[] = {
- {"k6_m6", 66666666, 1.0},
- { "k6_m6", 100000000, 1.5},
- { "k6_m6", 133333333, 2.0},
- { "k6_m6", 166666666, 2.5},
- { "k6_m6", 200000000, 3.0},
- { "k6_m6", 233333333, 3.5},
- { "k6_m7", 100000000, 1.5},
- { "k6_m7", 133333333, 2.0},
- { "k6_m7", 166666666, 2.5},
- { "k6_m7", 200000000, 3.0},
- { "k6_m7", 233333333, 3.5},
- { "k6_m7", 266666666, 4.0},
- { "k6_m7", 300000000, 4.5},
- { "k6_2", 100000000, 1.5},
- { "k6_2", 133333333, 2.0},
- { "k6_2", 166666666, 2.5},
- { "k6_2", 200000000, 3.0},
- { "k6_2", 233333333, 3.5},
- { "k6_2", 266666666, 4.0},
- { "k6_2", 300000000, 3.0},
- { "k6_2", 332500000, 3.5},
- { "k6_2", 350000000, 3.5},
- { "k6_2", 366666666, 5.5},
- { "k6_2", 380000000, 4.0},
- { "k6_2", 400000000, 4.0},
- { "k6_2", 450000000, 4.5},
- { "k6_2", 475000000, 5.0},
- { "k6_2", 500000000, 5.0},
- { "k6_2", 533333333, 5.5},
- { "k6_2", 550000000, 5.5},
- { "k6_2p", 100000000, 1.5},
- { "k6_2p", 133333333, 2.0},
- { "k6_2p", 166666666, 2.5},
- { "k6_2p", 200000000, 3.0},
- { "k6_2p", 233333333, 3.5},
- { "k6_2p", 266666666, 4.0},
- { "k6_2p", 300000000, 3.0},
- { "k6_2p", 332500000, 3.5},
- { "k6_2p", 350000000, 3.5},
- { "k6_2p", 366666666, 5.5},
- { "k6_2p", 380000000, 4.0},
- { "k6_2p", 400000000, 4.0},
- { "k6_2p", 450000000, 4.5},
- { "k6_2p", 475000000, 5.0},
- { "k6_2p", 500000000, 5.0},
- { "k6_2p", 533333333, 5.5},
- { "k6_2p", 550000000, 5.5},
- { "k6_3", 100000000, 1.5},
- { "k6_3", 133333333, 2.0},
- { "k6_3", 166666666, 2.5},
- { "k6_3", 200000000, 3.0},
- { "k6_3", 233333333, 3.5},
- { "k6_3", 266666666, 4.0},
- { "k6_3", 300000000, 3.0},
- { "k6_3", 332500000, 3.5},
- { "k6_3", 350000000, 3.5},
- { "k6_3", 366666666, 5.5},
- { "k6_3", 380000000, 4.0},
- { "k6_3", 400000000, 4.0},
- { "k6_3", 450000000, 4.5},
- { "k6_3p", 75000000, 1.5},
- { "k6_3p", 100000000, 1.5},
- { "k6_3p", 133333333, 2.0},
- { "k6_3p", 166666666, 2.5},
- { "k6_3p", 200000000, 3.0},
- { "k6_3p", 233333333, 3.5},
- { "k6_3p", 266666666, 4.0},
- { "k6_3p", 300000000, 3.0},
- { "k6_3p", 332500000, 3.5},
- { "k6_3p", 350000000, 3.5},
- { "k6_3p", 366666666, 5.5},
- { "k6_3p", 380000000, 4.0},
- { "k6_3p", 400000000, 4.0},
- { "k6_3p", 450000000, 4.5},
- { "k6_3p", 475000000, 5.0},
- { "k6_3p", 500000000, 5.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_PentiumPro[] = {
- {"pentiumpro", 50000000, 1.0},
- { "pentiumpro", 60000000, 1.0},
- { "pentiumpro", 66666666, 1.0},
- { "pentiumpro", 75000000, 1.5},
- { "pentiumpro", 150000000, 2.5},
- { "pentiumpro", 166666666, 2.5},
- { "pentiumpro", 180000000, 3.0},
- { "pentiumpro", 200000000, 3.0},
- { "pentium2_od", 50000000, 1.0},
- { "pentium2_od", 60000000, 1.0},
- { "pentium2_od", 66666666, 1.0},
- { "pentium2_od", 75000000, 1.5},
- { "pentium2_od", 210000000, 3.5},
- { "pentium2_od", 233333333, 3.5},
- { "pentium2_od", 240000000, 4.0},
- { "pentium2_od", 266666666, 4.0},
- { "pentium2_od", 270000000, 4.5},
- { "pentium2_od", 300000000, 4.5},
- { "pentium2_od", 300000000, 5.0},
- { "pentium2_od", 333333333, 5.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_PentiumII66[] = {
- {"pentium2_klamath", 50000000, 1.0},
- { "pentium2_klamath", 60000000, 1.0},
- { "pentium2_klamath", 66666666, 1.0},
- { "pentium2_klamath", 75000000, 1.5},
- { "pentium2_klamath", 233333333, 3.5},
- { "pentium2_klamath", 266666666, 4.0},
- { "pentium2_klamath", 300000000, 4.5},
- { "pentium2_deschutes", 50000000, 1.0},
- { "pentium2_deschutes", 60000000, 1.0},
- { "pentium2_deschutes", 66666666, 1.0},
- { "pentium2_deschutes", 75000000, 1.5},
- { "pentium2_deschutes", 266666666, 4.0},
- { "pentium2_deschutes", 300000000, 4.5},
- { "pentium2_deschutes", 333333333, 5.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_PentiumII[] = {
- {"pentium2_klamath", 50000000, 1.0},
- { "pentium2_klamath", 60000000, 1.0},
- { "pentium2_klamath", 66666666, 1.0},
- { "pentium2_klamath", 75000000, 1.5},
- { "pentium2_klamath", 233333333, 3.5},
- { "pentium2_klamath", 266666666, 4.0},
- { "pentium2_klamath", 300000000, 4.5},
- { "pentium2_deschutes", 50000000, 1.0},
- { "pentium2_deschutes", 60000000, 1.0},
- { "pentium2_deschutes", 66666666, 1.0},
- { "pentium2_deschutes", 75000000, 1.5},
- { "pentium2_deschutes", 266666666, 4.0},
- { "pentium2_deschutes", 300000000, 4.5},
- { "pentium2_deschutes", 333333333, 5.0},
- { "pentium2_deschutes", 350000000, 3.5},
- { "pentium2_deschutes", 400000000, 4.0},
- { "pentium2_deschutes", 450000000, 4.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Xeon[] = {
- {"pentium2_xeon", 75000000, 1.5},
- { "pentium2_xeon", 100000000, 1.5},
- { "pentium2_xeon", 133333333, 2.0},
- { "pentium2_xeon", 166666666, 2.5},
- { "pentium2_xeon", 400000000, 4.0},
- { "pentium2_xeon", 450000000, 4.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Celeron[] = {
- {"celeron_mendocino", 66666666, 1.0},
- { "celeron_mendocino", 100000000, 1.5},
- { "celeron_mendocino", 133333333, 2.0},
- { "celeron_mendocino", 166666666, 2.5},
- { "celeron_mendocino", 300000000, 4.5},
- { "celeron_mendocino", 333333333, 5.0},
- { "celeron_mendocino", 366666666, 5.5},
- { "celeron_mendocino", 400000000, 6.0},
- { "celeron_mendocino", 433333333, 6.5},
- { "celeron_mendocino", 466666666, 7.0},
- { "celeron_mendocino", 500000000, 7.5},
- { "celeron_mendocino", 533333333, 8.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_PentiumIID[] = {
- {"pentium2_deschutes", 50000000, 1.0},
- { "pentium2_deschutes", 60000000, 1.0},
- { "pentium2_deschutes", 66666666, 1.0},
- { "pentium2_deschutes", 75000000, 1.5},
- { "pentium2_deschutes", 266666666, 4.0},
- { "pentium2_deschutes", 300000000, 4.5},
- { "pentium2_deschutes", 333333333, 5.0},
- { "pentium2_deschutes", 350000000, 3.5},
- { "pentium2_deschutes", 400000000, 4.0},
- { "pentium2_deschutes", 450000000, 4.5},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t cpus_Cyrix3[] = {
- {"c3_samuel", 66666666, 1.0},
- { "c3_samuel", 233333333, 3.5},
- { "c3_samuel", 266666666, 4.0},
- { "c3_samuel", 300000000, 4.5},
- { "c3_samuel", 333333333, 5.0},
- { "c3_samuel", 350000000, 3.5},
- { "c3_samuel", 400000000, 4.0},
- { "c3_samuel", 450000000, 4.5},
- { "c3_samuel", 500000000, 5.0},
- { "c3_samuel", 550000000, 5.5},
- { "c3_samuel", 600000000, 6.0},
- { "c3_samuel", 650000000, 6.5},
- { "c3_samuel", 700000000, 7.0},
- { NULL, 0, 0 }
-};
-
-static const cpu_legacy_table_t *cputables_8088[4] = { cpus_8088 };
-static const cpu_legacy_table_t *cputables_pcjr[4] = { cpus_pcjr };
-static const cpu_legacy_table_t *cputables_europc[4] = { cpus_europc };
-static const cpu_legacy_table_t *cputables_pc1512[4] = { cpus_pc1512 };
-static const cpu_legacy_table_t *cputables_8086[4] = { cpus_8086 };
-static const cpu_legacy_table_t *cputables_286[4] = { cpus_286 };
-static const cpu_legacy_table_t *cputables_ibmat[4] = { cpus_ibmat };
-static const cpu_legacy_table_t *cputables_ps1_m2011[4] = { cpus_ps1_m2011 };
-static const cpu_legacy_table_t *cputables_ps2_m30_286_IBM486SLC[4] = { cpus_ps2_m30_286, cpus_IBM486SLC };
-static const cpu_legacy_table_t *cputables_ibmxt286[4] = { cpus_ibmxt286 };
-static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC[4] = { cpus_i386SX, cpus_Am386SX, cpus_486SLC };
-static const cpu_legacy_table_t *cputables_ALiM6117[4] = { cpus_ALiM6117 };
-static const cpu_legacy_table_t *cputables_i386SX_Am386SX_486SLC_IBM486SLC[4] = { cpus_i386SX, cpus_Am386SX, cpus_486SLC, cpus_IBM486SLC };
-static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC[4] = { cpus_i386DX, cpus_Am386DX, cpus_486DLC };
-static const cpu_legacy_table_t *cputables_i386DX_Am386DX_486DLC_IBM486BL[4] = { cpus_i386DX, cpus_Am386DX, cpus_486DLC, cpus_IBM486BL };
-static const cpu_legacy_table_t *cputables_i486_Am486_Cx486[4] = { cpus_i486, cpus_Am486, cpus_Cx486 };
-static const cpu_legacy_table_t *cputables_i486S1_Am486S1_Cx486S1[4] = { cpus_i486S1, cpus_Am486S1, cpus_Cx486S1 };
-static const cpu_legacy_table_t *cputables_IBM486SLC[4] = { cpus_IBM486SLC };
-static const cpu_legacy_table_t *cputables_i486_PC330[4] = { cpus_i486_PC330 };
-static const cpu_legacy_table_t *cputables_STPCDX[4] = { cpus_STPCDX };
-static const cpu_legacy_table_t *cputables_STPCDX2[4] = { cpus_STPCDX2 };
-static const cpu_legacy_table_t *cputables_Pentium5V[4] = { cpus_Pentium5V };
-static const cpu_legacy_table_t *cputables_PentiumS5_WinChip_K5[4] = { cpus_PentiumS5, cpus_WinChip, cpus_K5 };
-static const cpu_legacy_table_t *cputables_Pentium3V_WinChip_K5_6x863V[4] = { cpus_Pentium3V, cpus_WinChip, cpus_K5, cpus_6x863V };
-static const cpu_legacy_table_t *cputables_Pentium3V_K5[4] = { cpus_Pentium3V, cpus_K5 };
-static const cpu_legacy_table_t *cputables_Pentium_WinChip_K56_6x86[4] = { cpus_Pentium, cpus_WinChip, cpus_K56, cpus_6x86 };
-static const cpu_legacy_table_t *cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7[4] = { cpus_Pentium, cpus_WinChip_SS7, cpus_K56_SS7, cpus_6x86SS7 };
-static const cpu_legacy_table_t *cputables_PentiumPro[4] = { cpus_PentiumPro };
-static const cpu_legacy_table_t *cputables_PentiumII66[4] = { cpus_PentiumII66 };
-static const cpu_legacy_table_t *cputables_PentiumII_Celeron_Cyrix3[4] = { cpus_PentiumII, cpus_Celeron, cpus_Cyrix3 };
-static const cpu_legacy_table_t *cputables_Xeon[4] = { cpus_Xeon };
-static const cpu_legacy_table_t *cputables_Celeron_Cyrix3[4] = { cpus_Celeron, cpus_Cyrix3 };
-static const cpu_legacy_table_t *cputables_Celeron[4] = { cpus_Celeron };
-static const cpu_legacy_table_t *cputables_PentiumIID_Celeron[4] = { cpus_PentiumIID, cpus_Celeron };
-
-const cpu_legacy_machine_t cpu_legacy_table[] = {
- {"ibmpc", cputables_8088 },
- { "ibmpc82", cputables_8088 },
- { "ibmpcjr", cputables_pcjr },
- { "ibmxt", cputables_8088 },
- { "ibmxt86", cputables_8088 },
- { "americxt", cputables_8088 },
- { "amixt", cputables_8088 },
- { "portable", cputables_8088 },
- { "dtk", cputables_8088 },
- { "genxt", cputables_8088 },
- { "jukopc", cputables_8088 },
- { "openxt", cputables_8088 },
- { "pxxt", cputables_8088 },
- { "europc", cputables_europc },
- { "tandy", cputables_europc },
- { "tandy1000hx", cputables_europc },
- { "t1000", cputables_8088 },
- { "ltxt", cputables_8088 },
- { "xi8088", cputables_8088 },
- { "zdsupers", cputables_8088 },
- { "pc1512", cputables_pc1512 },
- { "pc1640", cputables_8086 },
- { "pc2086", cputables_8086 },
- { "pc3086", cputables_8086 },
- { "pc200", cputables_8086 },
- { "ppc512", cputables_8086 },
- { "deskpro", cputables_8086 },
- { "m24", cputables_8086 },
- { "iskra3104", cputables_8086 },
- { "tandy1000sl2", cputables_8086 },
- { "t1200", cputables_8086 },
- { "lxt3", cputables_8086 },
- { "hed919", cputables_286 },
- { "ibmat", cputables_ibmat },
- { "ibmps1es", cputables_ps1_m2011 },
- { "ibmps2_m30_286", cputables_ps2_m30_286_IBM486SLC },
- { "ibmxt286", cputables_ibmxt286 },
- { "ibmatami", cputables_ibmat },
- { "cmdpc30", cputables_286 },
- { "portableii", cputables_286 },
- { "portableiii", cputables_286 },
- { "mr286", cputables_286 },
- { "open_at", cputables_286 },
- { "ibmatpx", cputables_ibmat },
- { "ibmatquadtel", cputables_ibmat },
- { "siemens", cputables_286 },
- { "t3100e", cputables_286 },
- { "quadt286", cputables_286 },
- { "tg286m", cputables_286 },
- { "ami286", cputables_286 },
- { "px286", cputables_286 },
- { "award286", cputables_286 },
- { "gw286ct", cputables_286 },
- { "gdc212m", cputables_286 },
- { "super286c", cputables_286 },
- { "super286tr", cputables_286 },
- { "spc4200p", cputables_286 },
- { "spc4216p", cputables_286 },
- { "deskmaster286", cputables_286 },
- { "ibmps2_m50", cputables_ps2_m30_286_IBM486SLC },
- { "ibmps1_2121", cputables_i386SX_Am386SX_486SLC },
- { "ibmps1_2121_isa", cputables_i386SX_Am386SX_486SLC },
- { "arb1375", cputables_ALiM6117 },
- { "pja511m", cputables_ALiM6117 },
- { "ama932j", cputables_i386SX_Am386SX_486SLC },
- { "adi386sx", cputables_i386SX_Am386SX_486SLC },
- { "shuttle386sx", cputables_i386SX_Am386SX_486SLC },
- { "dtk386", cputables_i386SX_Am386SX_486SLC },
- { "awardsx", cputables_i386SX_Am386SX_486SLC },
- { "cmdsl386sx25", cputables_i386SX_Am386SX_486SLC },
- { "kmxc02", cputables_i386SX_Am386SX_486SLC },
- { "megapc", cputables_i386SX_Am386SX_486SLC },
- { "ibmps2_m55sx", cputables_i386SX_Am386SX_486SLC_IBM486SLC },
- { "acc386", cputables_i386DX_Am386DX_486DLC },
- { "ecs386", cputables_i386DX_Am386DX_486DLC },
- { "portableiii386", cputables_i386DX_Am386DX_486DLC },
- { "micronics386", cputables_i386DX_Am386DX_486DLC },
- { "asus386", cputables_i386DX_Am386DX_486DLC },
- { "ustechnologies386", cputables_i386DX_Am386DX_486DLC },
- { "award386dx", cputables_i386DX_Am386DX_486DLC },
- { "ibmps2_m70_type3", cputables_i386DX_Am386DX_486DLC_IBM486BL },
- { "ibmps2_m80", cputables_i386DX_Am386DX_486DLC_IBM486BL },
- { "pb410a", cputables_i486_Am486_Cx486 },
- { "acera1g", cputables_i486_Am486_Cx486 },
- { "win486", cputables_i486_Am486_Cx486 },
- { "ali1429", cputables_i486S1_Am486S1_Cx486S1 },
- { "cs4031", cputables_i486S1_Am486S1_Cx486S1 },
- { "rycleopardlx", cputables_IBM486SLC },
- { "award486", cputables_i486S1_Am486S1_Cx486S1 },
- { "ami486", cputables_i486S1_Am486S1_Cx486S1 },
- { "mr486", cputables_i486_Am486_Cx486 },
- { "pc330_6571", cputables_i486_PC330 },
- { "403tg", cputables_i486_Am486_Cx486 },
- { "sis401", cputables_i486_Am486_Cx486 },
- { "valuepoint433", cputables_i486_Am486_Cx486 },
- { "ami471", cputables_i486_Am486_Cx486 },
- { "win471", cputables_i486_Am486_Cx486 },
- { "vi15g", cputables_i486_Am486_Cx486 },
- { "vli486sv2g", cputables_i486_Am486_Cx486 },
- { "dtk486", cputables_i486_Am486_Cx486 },
- { "px471", cputables_i486_Am486_Cx486 },
- { "486vchd", cputables_i486S1_Am486S1_Cx486S1 },
- { "ibmps1_2133", cputables_i486S1_Am486S1_Cx486S1 },
- { "vect486vl", cputables_i486S1_Am486S1_Cx486S1 },
- { "ibmps2_m70_type4", cputables_i486S1_Am486S1_Cx486S1 },
- { "abpb4", cputables_i486_Am486_Cx486 },
- { "486ap4", cputables_i486_Am486_Cx486 },
- { "486sp3g", cputables_i486_Am486_Cx486 },
- { "alfredo", cputables_i486_Am486_Cx486 },
- { "ls486e", cputables_i486_Am486_Cx486 },
- { "m4li", cputables_i486_Am486_Cx486 },
- { "r418", cputables_i486_Am486_Cx486 },
- { "4sa2", cputables_i486_Am486_Cx486 },
- { "4dps", cputables_i486_Am486_Cx486 },
- { "itoxstar", cputables_STPCDX },
- { "arb1479", cputables_STPCDX2 },
- { "pcm9340", cputables_STPCDX2 },
- { "pcm5330", cputables_STPCDX2 },
- { "486vipio2", cputables_i486_Am486_Cx486 },
- { "p5mp3", cputables_Pentium5V },
- { "dellxp60", cputables_Pentium5V },
- { "opti560l", cputables_Pentium5V },
- { "ambradp60", cputables_Pentium5V },
- { "valuepointp60", cputables_Pentium5V },
- { "revenge", cputables_Pentium5V },
- { "586mc1", cputables_Pentium5V },
- { "pb520r", cputables_Pentium5V },
- { "excalibur", cputables_Pentium5V },
- { "plato", cputables_PentiumS5_WinChip_K5 },
- { "ambradp90", cputables_PentiumS5_WinChip_K5 },
- { "430nx", cputables_PentiumS5_WinChip_K5 },
- { "acerv30", cputables_PentiumS5_WinChip_K5 },
- { "apollo", cputables_PentiumS5_WinChip_K5 },
- { "vectra54", cputables_PentiumS5_WinChip_K5 },
- { "zappa", cputables_PentiumS5_WinChip_K5 },
- { "powermate_v", cputables_PentiumS5_WinChip_K5 },
- { "mb500n", cputables_PentiumS5_WinChip_K5 },
- { "p54tp4xe", cputables_Pentium3V_WinChip_K5_6x863V },
- { "mr586", cputables_Pentium3V_WinChip_K5_6x863V },
- { "gw2katx", cputables_Pentium3V_WinChip_K5_6x863V },
- { "thor", cputables_Pentium3V_WinChip_K5_6x863V },
- { "mrthor", cputables_Pentium3V_WinChip_K5_6x863V },
- { "endeavor", cputables_Pentium3V_WinChip_K5_6x863V },
- { "pb640", cputables_Pentium3V_WinChip_K5_6x863V },
- { "chariot", cputables_Pentium3V_K5 },
- { "acerm3a", cputables_Pentium3V_WinChip_K5_6x863V },
- { "ap53", cputables_Pentium3V_WinChip_K5_6x863V },
- { "8500tuc", cputables_Pentium3V_WinChip_K5_6x863V },
- { "p55t2s", cputables_Pentium3V_WinChip_K5_6x863V },
- { "acerv35n", cputables_Pentium_WinChip_K56_6x86 },
- { "p55t2p4", cputables_Pentium_WinChip_K56_6x86 },
- { "m7shi", cputables_Pentium_WinChip_K56_6x86 },
- { "tc430hx", cputables_Pentium_WinChip_K56_6x86 },
- { "equium5200", cputables_Pentium_WinChip_K56_6x86 },
- { "pcv240", cputables_Pentium_WinChip_K56_6x86 },
- { "p65up5_cp55t2d", cputables_Pentium_WinChip_K56_6x86 },
- { "p55tvp4", cputables_Pentium_WinChip_K56_6x86 },
- { "8500tvxa", cputables_Pentium_WinChip_K56_6x86 },
- { "presario4500", cputables_Pentium_WinChip_K56_6x86 },
- { "p55va", cputables_Pentium_WinChip_K56_6x86 },
- { "gw2kte", cputables_Pentium_WinChip_K56_6x86 },
- { "brio80xx", cputables_Pentium_WinChip_K56_6x86 },
- { "pb680", cputables_Pentium_WinChip_K56_6x86 },
- { "430vx", cputables_Pentium_WinChip_K56_6x86 },
- { "nupro592", cputables_Pentium_WinChip_K56_6x86 },
- { "tx97", cputables_Pentium_WinChip_K56_6x86 },
- { "an430tx", cputables_Pentium_WinChip_K56_6x86 },
- { "ym430tx", cputables_Pentium_WinChip_K56_6x86 },
- { "mb540n", cputables_Pentium_WinChip_K56_6x86 },
- { "p5mms98", cputables_Pentium_WinChip_K56_6x86 },
- { "ficva502", cputables_Pentium_WinChip_K56_6x86 },
- { "ficpa2012", cputables_Pentium_WinChip_K56_6x86 },
- { "ax59pro", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7},
- { "ficva503p", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7},
- { "ficva503a", cputables_Pentium_WinChip_SS7_K56_SS7_6x86SS7},
- { "v60n", cputables_PentiumPro },
- { "p65up5_cp6nd", cputables_PentiumPro },
- { "8600ttc", cputables_PentiumPro },
- { "686nx", cputables_PentiumPro },
- { "ap440fx", cputables_PentiumPro },
- { "vs440fx", cputables_PentiumPro },
- { "m6mi", cputables_PentiumPro },
- { "mb600n", cputables_PentiumPro },
- { "p65up5_cpknd", cputables_PentiumII66 },
- { "kn97", cputables_PentiumII66 },
- { "lx6", cputables_PentiumII66 },
- { "spitfire", cputables_PentiumII66 },
- { "p6i440e2", cputables_PentiumII66 },
- { "p2bls", cputables_PentiumII_Celeron_Cyrix3 },
- { "p3bf", cputables_PentiumII_Celeron_Cyrix3 },
- { "bf6", cputables_PentiumII_Celeron_Cyrix3 },
- { "ax6bc", cputables_PentiumII_Celeron_Cyrix3 },
- { "atc6310bxii", cputables_PentiumII_Celeron_Cyrix3 },
- { "686bx", cputables_PentiumII_Celeron_Cyrix3 },
- { "tsunamiatx", cputables_PentiumII_Celeron_Cyrix3 },
- { "p6sba", cputables_PentiumII_Celeron_Cyrix3 },
- { "ergox365", cputables_PentiumII_Celeron_Cyrix3 },
- { "ficka6130", cputables_PentiumII_Celeron_Cyrix3 },
- { "6gxu", cputables_Xeon },
- { "fw6400gx", cputables_Xeon },
- { "s2dge", cputables_Xeon },
- { "s370slm", cputables_Celeron_Cyrix3 },
- { "awo671r", cputables_Celeron_Cyrix3 },
- { "cubx", cputables_Celeron_Cyrix3 },
- { "atc7020bxii", cputables_Celeron_Cyrix3 },
- { "ambx133", cputables_Celeron_Cyrix3 },
- { "trinity371", cputables_Celeron },
- { "63a", cputables_Celeron_Cyrix3 },
- { "apas3", cputables_Celeron_Cyrix3 },
- { "wcf681", cputables_Celeron_Cyrix3 },
- { "6via90ap", cputables_Celeron_Cyrix3 },
- { "p6bap", cputables_Celeron_Cyrix3 },
- { "603tcf", cputables_Celeron_Cyrix3 },
- { "vpc2007", cputables_PentiumIID_Celeron },
- { NULL, NULL }
-};
diff --git a/src/cpu/softfloat/CMakeLists.txt b/src/cpu/softfloat/CMakeLists.txt
deleted file mode 100644
index 9361571855..0000000000
--- a/src/cpu/softfloat/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# 86Box A hypervisor and IBM PC system emulator that specializes in
-# running old operating systems and software designed for IBM
-# PC systems and compatibles from 1981 through fairly recent
-# system designs based on the PCI bus.
-#
-# This file is part of the 86Box distribution.
-#
-# CMake build script.
-#
-# Authors: David Hrdlička,
-#
-# Copyright 2020-2021 David Hrdlička.
-#
-
-add_library(softfloat OBJECT f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc softfloat_poly.cc softfloat.cc softfloat16.cc
- softfloat-muladd.cc softfloat-round-pack.cc softfloat-specialize.cc softfloatx80.cc)
diff --git a/src/cpu/softfloat/config.h b/src/cpu/softfloat/config.h
deleted file mode 100644
index 9e39c2d29c..0000000000
--- a/src/cpu/softfloat/config.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef EMU_SF_CONFIG_H
-#define EMU_SF_CONFIG_H
-
-#include
-
-typedef int8_t flag;
-typedef uint8_t uint8;
-typedef int8_t int8;
-typedef uint16_t uint16;
-typedef int16_t int16;
-typedef uint32_t uint32;
-typedef int32_t int32;
-typedef uint64_t uint64;
-typedef int64_t int64;
-
-/*----------------------------------------------------------------------------
-| Each of the following `typedef's defines a type that holds integers
-| of _exactly_ the number of bits specified. For instance, for most
-| implementation of C, `bits16' and `sbits16' should be `typedef'ed to
-| `unsigned short int' and `signed short int' (or `short int'), respectively.
-*----------------------------------------------------------------------------*/
-typedef uint8_t bits8;
-typedef int8_t sbits8;
-typedef uint16_t bits16;
-typedef int16_t sbits16;
-typedef uint32_t bits32;
-typedef int32_t sbits32;
-typedef uint64_t bits64;
-typedef int64_t sbits64;
-
-typedef uint8_t Bit8u;
-typedef int8_t Bit8s;
-typedef uint16_t Bit16u;
-typedef int16_t Bit16s;
-typedef uint32_t Bit32u;
-typedef int32_t Bit32s;
-typedef uint64_t Bit64u;
-typedef int64_t Bit64s;
-
-/*----------------------------------------------------------------------------
-| The `LIT64' macro takes as its argument a textual integer literal and
-| if necessary ``marks'' the literal as having a 64-bit integer type.
-| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
-| appended with the letters `LL' standing for `long long', which is `gcc's
-| name for the 64-bit integer type. Some compilers may allow `LIT64' to be
-| defined as the identity macro: `#define LIT64( a ) a'.
-*----------------------------------------------------------------------------*/
-#define BX_CONST64(a) a##LL
-#define BX_CPP_INLINE static __inline
-
-#endif /*EMU_SF_CONFIG_H*/
diff --git a/src/cpu/softfloat/softfloat-compare.h b/src/cpu/softfloat/softfloat-compare.h
deleted file mode 100644
index 8b9821460b..0000000000
--- a/src/cpu/softfloat/softfloat-compare.h
+++ /dev/null
@@ -1,496 +0,0 @@
-/*============================================================================
-This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#ifndef _SOFTFLOAT_COMPARE_H_
-#define _SOFTFLOAT_COMPARE_H_
-
-#include "softfloat.h"
-
-// ======= float32 ======= //
-
-typedef int (*float32_compare_method)(float32, float32, struct float_status_t *status);
-
-// 0x00
-BX_CPP_INLINE int float32_eq_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_equal);
-}
-
-// 0x01
-BX_CPP_INLINE int float32_lt_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_less);
-}
-
-// 0x02
-BX_CPP_INLINE int float32_le_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_equal);
-}
-
-// 0x03
-BX_CPP_INLINE int float32_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_unordered);
-}
-
-// 0x04
-BX_CPP_INLINE int float32_neq_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation != float_relation_equal);
-}
-
-// 0x05
-BX_CPP_INLINE int float32_nlt_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation != float_relation_less);
-}
-
-// 0x06
-BX_CPP_INLINE int float32_nle_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation != float_relation_less) && (relation != float_relation_equal);
-}
-
-// 0x07
-BX_CPP_INLINE int float32_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation != float_relation_unordered);
-}
-
-// 0x08
-BX_CPP_INLINE int float32_eq_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_equal) || (relation == float_relation_unordered);
-}
-
-// 0x09
-BX_CPP_INLINE int float32_nge_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_unordered);
-}
-
-// 0x0a
-BX_CPP_INLINE int float32_ngt_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation != float_relation_greater);
-}
-
-// 0x0b
-BX_CPP_INLINE int float32_false_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- float32_compare_quiet(a, b, status);
- return 0;
-}
-
-// 0x0c
-BX_CPP_INLINE int float32_neq_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation != float_relation_equal) && (relation != float_relation_unordered);
-}
-
-// 0x0d
-BX_CPP_INLINE int float32_ge_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_greater) || (relation == float_relation_equal);
-}
-
-// 0x0e
-BX_CPP_INLINE int float32_gt_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_greater);
-}
-
-// 0x0f
-BX_CPP_INLINE int float32_true_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- float32_compare_quiet(a, b, status);
- return 1;
-}
-
-// 0x10
-BX_CPP_INLINE int float32_eq_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_equal);
-}
-
-// 0x11
-BX_CPP_INLINE int float32_lt_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_less);
-}
-
-// 0x12
-BX_CPP_INLINE int float32_le_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_equal);
-}
-
-// 0x13
-BX_CPP_INLINE int float32_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_unordered);
-}
-
-// 0x14
-BX_CPP_INLINE int float32_neq_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation != float_relation_equal);
-}
-
-// 0x15
-BX_CPP_INLINE int float32_nlt_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation != float_relation_less);
-}
-
-// 0x16
-BX_CPP_INLINE int float32_nle_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation != float_relation_less) && (relation != float_relation_equal);
-}
-
-// 0x17
-BX_CPP_INLINE int float32_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation != float_relation_unordered);
-}
-
-// 0x18
-BX_CPP_INLINE int float32_eq_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation == float_relation_equal) || (relation == float_relation_unordered);
-}
-
-// 0x19
-BX_CPP_INLINE int float32_nge_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_unordered);
-}
-
-// 0x1a
-BX_CPP_INLINE int float32_ngt_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation != float_relation_greater);
-}
-
-// 0x1b
-BX_CPP_INLINE int float32_false_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- float32_compare_two(a, b, status);
- return 0;
-}
-
-// 0x1c
-BX_CPP_INLINE int float32_neq_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_two(a, b, status);
- return (relation != float_relation_equal) && (relation != float_relation_unordered);
-}
-
-// 0x1d
-BX_CPP_INLINE int float32_ge_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_greater) || (relation == float_relation_equal);
-}
-
-// 0x1e
-BX_CPP_INLINE int float32_gt_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- int relation = float32_compare_quiet(a, b, status);
- return (relation == float_relation_greater);
-}
-
-// 0x1f
-BX_CPP_INLINE int float32_true_signalling(float32 a, float32 b, struct float_status_t *status)
-{
- float32_compare_two(a, b, status);
- return 1;
-}
-
-// ======= float64 ======= //
-
-typedef int (*float64_compare_method)(float64, float64, struct float_status_t *status);
-
-// 0x00
-BX_CPP_INLINE int float64_eq_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_equal);
-}
-
-// 0x01
-BX_CPP_INLINE int float64_lt_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_less);
-}
-
-// 0x02
-BX_CPP_INLINE int float64_le_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_equal);
-}
-
-// 0x03
-BX_CPP_INLINE int float64_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_unordered);
-}
-
-// 0x04
-BX_CPP_INLINE int float64_neq_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation != float_relation_equal);
-}
-
-// 0x05
-BX_CPP_INLINE int float64_nlt_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation != float_relation_less);
-}
-
-// 0x06
-BX_CPP_INLINE int float64_nle_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation != float_relation_less) && (relation != float_relation_equal);
-}
-
-// 0x07
-BX_CPP_INLINE int float64_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation != float_relation_unordered);
-}
-
-// 0x08
-BX_CPP_INLINE int float64_eq_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_equal) || (relation == float_relation_unordered);
-}
-
-// 0x09
-BX_CPP_INLINE int float64_nge_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_unordered);
-}
-
-// 0x0a
-BX_CPP_INLINE int float64_ngt_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation != float_relation_greater);
-}
-
-// 0x0b
-BX_CPP_INLINE int float64_false_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- float64_compare_quiet(a, b, status);
- return 0;
-}
-
-// 0x0c
-BX_CPP_INLINE int float64_neq_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation != float_relation_equal) && (relation != float_relation_unordered);
-}
-
-// 0x0d
-BX_CPP_INLINE int float64_ge_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_greater) || (relation == float_relation_equal);
-}
-
-// 0x0e
-BX_CPP_INLINE int float64_gt_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_greater);
-}
-
-// 0x0f
-BX_CPP_INLINE int float64_true_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- float64_compare_quiet(a, b, status);
- return 1;
-}
-
-// 0x10
-BX_CPP_INLINE int float64_eq_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_equal);
-}
-
-// 0x11
-BX_CPP_INLINE int float64_lt_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_less);
-}
-
-// 0x12
-BX_CPP_INLINE int float64_le_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_equal);
-}
-
-// 0x13
-BX_CPP_INLINE int float64_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_unordered);
-}
-
-// 0x14
-BX_CPP_INLINE int float64_neq_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation != float_relation_equal);
-}
-
-// 0x15
-BX_CPP_INLINE int float64_nlt_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation != float_relation_less);
-}
-
-// 0x16
-BX_CPP_INLINE int float64_nle_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation != float_relation_less) && (relation != float_relation_equal);
-}
-
-// 0x17
-BX_CPP_INLINE int float64_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation != float_relation_unordered);
-}
-
-// 0x18
-BX_CPP_INLINE int float64_eq_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation == float_relation_equal) || (relation == float_relation_unordered);
-}
-
-// 0x19
-BX_CPP_INLINE int float64_nge_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_less) || (relation == float_relation_unordered);
-}
-
-// 0x1a
-BX_CPP_INLINE int float64_ngt_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation != float_relation_greater);
-}
-
-// 0x1b
-BX_CPP_INLINE int float64_false_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- float64_compare_two(a, b, status);
- return 0;
-}
-
-// 0x1c
-BX_CPP_INLINE int float64_neq_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_two(a, b, status);
- return (relation != float_relation_equal) && (relation != float_relation_unordered);
-}
-
-// 0x1d
-BX_CPP_INLINE int float64_ge_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_greater) || (relation == float_relation_equal);
-}
-
-// 0x1e
-BX_CPP_INLINE int float64_gt_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- int relation = float64_compare_quiet(a, b, status);
- return (relation == float_relation_greater);
-}
-
-// 0x1f
-BX_CPP_INLINE int float64_true_signalling(float64 a, float64 b, struct float_status_t *status)
-{
- float64_compare_two(a, b, status);
- return 1;
-}
-
-#endif
diff --git a/src/cpu/softfloat/softfloat-macros.h b/src/cpu/softfloat/softfloat-macros.h
deleted file mode 100644
index cb867bf5d1..0000000000
--- a/src/cpu/softfloat/softfloat-macros.h
+++ /dev/null
@@ -1,686 +0,0 @@
-/*============================================================================
-This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
-Arithmetic Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#ifndef _SOFTFLOAT_MACROS_H_
-#define _SOFTFLOAT_MACROS_H_
-
-/*----------------------------------------------------------------------------
-| Shifts `a' right by the number of bits given in `count'. If any nonzero
-| bits are shifted off, they are ``jammed'' into the least significant bit of
-| the result by setting the least significant bit to 1. The value of `count'
-| can be arbitrarily large; in particular, if `count' is greater than 16, the
-| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit16u shift16RightJamming(Bit16u a, int count)
-{
- Bit16u z;
-
- if (count == 0) {
- z = a;
- }
- else if (count < 16) {
- z = (a>>count) | ((a<<((-count) & 15)) != 0);
- }
- else {
- z = (a != 0);
- }
-
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Shifts `a' right by the number of bits given in `count'. If any nonzero
-| bits are shifted off, they are ``jammed'' into the least significant bit of
-| the result by setting the least significant bit to 1. The value of `count'
-| can be arbitrarily large; in particular, if `count' is greater than 32, the
-| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit32u shift32RightJamming(Bit32u a, int count)
-{
- Bit32u z;
-
- if (count == 0) {
- z = a;
- }
- else if (count < 32) {
- z = (a>>count) | ((a<<((-count) & 31)) != 0);
- }
- else {
- z = (a != 0);
- }
-
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Shifts `a' right by the number of bits given in `count'. If any nonzero
-| bits are shifted off, they are ``jammed'' into the least significant bit of
-| the result by setting the least significant bit to 1. The value of `count'
-| can be arbitrarily large; in particular, if `count' is greater than 64, the
-| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit64u shift64RightJamming(Bit64u a, int count)
-{
- Bit64u z;
-
- if (count == 0) {
- z = a;
- }
- else if (count < 64) {
- z = (a>>count) | ((a << ((-count) & 63)) != 0);
- }
- else {
- z = (a != 0);
- }
-
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
-| _plus_ the number of bits given in `count'. The shifted result is at most
-| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
-| bits shifted off form a second 64-bit result as follows: The _last_ bit
-| shifted off is the most-significant bit of the extra result, and the other
-| 63 bits of the extra result are all zero if and only if _all_but_the_last_
-| bits shifted off were all zero. This extra result is stored in the location
-| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
-| (This routine makes more sense if `a0' and `a1' are considered to form
-| a fixed-point value with binary point between `a0' and `a1'. This fixed-
-| point value is shifted right by the number of bits given in `count', and
-| the integer part of the result is returned at the location pointed to by
-| `z0Ptr'. The fractional part of the result may be slightly corrupted as
-| described above, and is returned at the location pointed to by `z1Ptr'.)
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
-{
- Bit64u z0, z1;
- int negCount = (-count) & 63;
-
- if (count == 0) {
- z1 = a1;
- z0 = a0;
- }
- else if (count < 64) {
- z1 = (a0<>count;
- }
- else {
- if (count == 64) {
- z1 = a0 | (a1 != 0);
- }
- else {
- z1 = ((a0 | a1) != 0);
- }
- z0 = 0;
- }
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-/*----------------------------------------------------------------------------
-| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
-| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
-| any carry out is lost. The result is broken into two 64-bit pieces which
-| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr)
-{
- Bit64u z1 = a1 + b1;
- *z1Ptr = z1;
- *z0Ptr = a0 + b0 + (z1 < a1);
-}
-
-/*----------------------------------------------------------------------------
-| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
-| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
-| 2^128, so any borrow out (carry out) is lost. The result is broken into two
-| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
-| `z1Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void
- sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr)
-{
- *z1Ptr = a1 - b1;
- *z0Ptr = a0 - b0 - (a1 < b1);
-}
-
-/*----------------------------------------------------------------------------
-| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
-| into two 64-bit pieces which are stored at the locations pointed to by
-| `z0Ptr' and `z1Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr)
-{
- Bit32u aHigh, aLow, bHigh, bLow;
- Bit64u z0, zMiddleA, zMiddleB, z1;
-
- aLow = (Bit32u) a;
- aHigh = (Bit32u)(a>>32);
- bLow = (Bit32u) b;
- bHigh = (Bit32u)(b>>32);
- z1 = ((Bit64u) aLow) * bLow;
- zMiddleA = ((Bit64u) aLow) * bHigh;
- zMiddleB = ((Bit64u) aHigh) * bLow;
- z0 = ((Bit64u) aHigh) * bHigh;
- zMiddleA += zMiddleB;
- z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32);
- zMiddleA <<= 32;
- z1 += zMiddleA;
- z0 += (z1 < zMiddleA);
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-/*----------------------------------------------------------------------------
-| Returns an approximation to the 64-bit integer quotient obtained by dividing
-| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
-| divisor `b' must be at least 2^63. If q is the exact quotient truncated
-| toward zero, the approximation returned lies between q and q + 2 inclusive.
-| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
-| unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-#ifdef USE_estimateDiv128To64
-static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b)
-{
- Bit64u b0, b1;
- Bit64u rem0, rem1, term0, term1;
- Bit64u z;
-
- if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF);
- b0 = b>>32;
- z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32;
- mul64To128(b, z, &term0, &term1);
- sub128(a0, a1, term0, term1, &rem0, &rem1);
- while (((Bit64s) rem0) < 0) {
- z -= BX_CONST64(0x100000000);
- b1 = b<<32;
- add128(rem0, rem1, b0, b1, &rem0, &rem1);
- }
- rem0 = (rem0<<32) | (rem1>>32);
- z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0;
- return z;
-}
-#endif
-
-/*----------------------------------------------------------------------------
-| Returns an approximation to the square root of the 32-bit significand given
-| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
-| `aExp' (the least significant bit) is 1, the integer returned approximates
-| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
-| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
-| case, the approximation returned lies strictly within +/-2 of the exact
-| value.
-*----------------------------------------------------------------------------*/
-
-#ifdef USE_estimateSqrt32
-static Bit32u estimateSqrt32(Bit16s aExp, Bit32u a)
-{
- static const Bit16u sqrtOddAdjustments[] = {
- 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
- 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
- };
- static const Bit16u sqrtEvenAdjustments[] = {
- 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
- 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
- };
- Bit32u z;
-
- int index = (a>>27) & 15;
- if (aExp & 1) {
- z = 0x4000 + (a>>17) - sqrtOddAdjustments[index];
- z = ((a / z)<<14) + (z<<15);
- a >>= 1;
- }
- else {
- z = 0x8000 + (a>>17) - sqrtEvenAdjustments[index];
- z = a / z + z;
- z = (0x20000 <= z) ? 0xFFFF8000 : (z<<15);
- if (z <= a) return (Bit32u) (((Bit32s) a)>>1);
- }
- return ((Bit32u) ((((Bit64u) a)<<31) / z)) + (z>>1);
-}
-#endif
-
-static const int countLeadingZeros8[] = {
- 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-#ifdef FLOAT16
-
-/*----------------------------------------------------------------------------
-| Returns the number of leading 0 bits before the most-significant 1 bit of
-| `a'. If `a' is zero, 16 is returned.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int countLeadingZeros16(Bit16u a)
-{
- int shiftCount = 0;
- if (a < 0x100) {
- shiftCount += 8;
- a <<= 8;
- }
- shiftCount += countLeadingZeros8[a>>8];
- return shiftCount;
-}
-
-#endif
-
-/*----------------------------------------------------------------------------
-| Returns the number of leading 0 bits before the most-significant 1 bit of
-| `a'. If `a' is zero, 32 is returned.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int countLeadingZeros32(Bit32u a)
-{
- int shiftCount = 0;
- if (a < 0x10000) {
- shiftCount += 16;
- a <<= 16;
- }
- if (a < 0x1000000) {
- shiftCount += 8;
- a <<= 8;
- }
- shiftCount += countLeadingZeros8[a>>24];
- return shiftCount;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the number of leading 0 bits before the most-significant 1 bit of
-| `a'. If `a' is zero, 64 is returned.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int countLeadingZeros64(Bit64u a)
-{
- int shiftCount = 0;
- if (a < BX_CONST64(0x100000000)) {
- shiftCount += 32;
- }
- else {
- a >>= 32;
- }
- shiftCount += countLeadingZeros32((Bit32u)(a));
- return shiftCount;
-}
-
-#ifdef FLOATX80
-
-/*----------------------------------------------------------------------------
-| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
-| number of bits given in `count'. Any bits shifted off are lost. The value
-| of `count' can be arbitrarily large; in particular, if `count' is greater
-| than 128, the result will be 0. The result is broken into two 64-bit pieces
-| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void shift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
-{
- Bit64u z0, z1;
- int negCount = (-count) & 63;
-
- if (count == 0) {
- z1 = a1;
- z0 = a0;
- }
- else if (count < 64) {
- z1 = (a0<>count);
- z0 = a0>>count;
- }
- else {
- z1 = (count < 128) ? (a0>>(count & 63)) : 0;
- z0 = 0;
- }
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-/*----------------------------------------------------------------------------
-| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
-| number of bits given in `count'. If any nonzero bits are shifted off, they
-| are ``jammed'' into the least significant bit of the result by setting the
-| least significant bit to 1. The value of `count' can be arbitrarily large;
-| in particular, if `count' is greater than 128, the result will be either
-| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
-| nonzero. The result is broken into two 64-bit pieces which are stored at
-| the locations pointed to by `z0Ptr' and `z1Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void shift128RightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
-{
- Bit64u z0, z1;
- int negCount = (-count) & 63;
-
- if (count == 0) {
- z1 = a1;
- z0 = a0;
- }
- else if (count < 64) {
- z1 = (a0<>count) | ((a1<>count;
- }
- else {
- if (count == 64) {
- z1 = a0 | (a1 != 0);
- }
- else if (count < 128) {
- z1 = (a0>>(count & 63)) | (((a0<>((-count) & 63));
-}
-
-/*----------------------------------------------------------------------------
-| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
-| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
-| modulo 2^192, so any carry out is lost. The result is broken into three
-| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
-| `z1Ptr', and `z2Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void add192(
- Bit64u a0,
- Bit64u a1,
- Bit64u a2,
- Bit64u b0,
- Bit64u b1,
- Bit64u b2,
- Bit64u *z0Ptr,
- Bit64u *z1Ptr,
- Bit64u *z2Ptr
-)
-{
- Bit64u z0, z1, z2;
- unsigned carry0, carry1;
-
- z2 = a2 + b2;
- carry1 = (z2 < a2);
- z1 = a1 + b1;
- carry0 = (z1 < a1);
- z0 = a0 + b0;
- z1 += carry1;
- z0 += (z1 < carry1);
- z0 += carry0;
- *z2Ptr = z2;
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-/*----------------------------------------------------------------------------
-| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
-| from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
-| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
-| result is broken into three 64-bit pieces which are stored at the locations
-| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void sub192(
- Bit64u a0,
- Bit64u a1,
- Bit64u a2,
- Bit64u b0,
- Bit64u b1,
- Bit64u b2,
- Bit64u *z0Ptr,
- Bit64u *z1Ptr,
- Bit64u *z2Ptr
-)
-{
- Bit64u z0, z1, z2;
- unsigned borrow0, borrow1;
-
- z2 = a2 - b2;
- borrow1 = (a2 < b2);
- z1 = a1 - b1;
- borrow0 = (a1 < b1);
- z0 = a0 - b0;
- z0 -= (z1 < borrow1);
- z1 -= borrow1;
- z0 -= borrow0;
- *z2Ptr = z2;
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
-| is equal to the 128-bit value formed by concatenating `b0' and `b1'.
-| Otherwise, returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int eq128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1)
-{
- return (a0 == b0) && (a1 == b1);
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
-| than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
-| Otherwise, returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int le128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1)
-{
- return (a0 < b0) || ((a0 == b0) && (a1 <= b1));
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
-| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
-| returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int lt128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1)
-{
- return (a0 < b0) || ((a0 == b0) && (a1 < b1));
-}
-
-#endif /* FLOATX80 */
-
-/*----------------------------------------------------------------------------
-| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
-| `b' to obtain a 192-bit product. The product is broken into three 64-bit
-| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
-| `z2Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void mul128By64To192(
- Bit64u a0,
- Bit64u a1,
- Bit64u b,
- Bit64u *z0Ptr,
- Bit64u *z1Ptr,
- Bit64u *z2Ptr
-)
-{
- Bit64u z0, z1, z2, more1;
-
- mul64To128(a1, b, &z1, &z2);
- mul64To128(a0, b, &z0, &more1);
- add128(z0, more1, 0, z1, &z0, &z1);
- *z2Ptr = z2;
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-#ifdef FLOAT128
-
-/*----------------------------------------------------------------------------
-| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
-| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
-| product. The product is broken into four 64-bit pieces which are stored at
-| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void mul128To256(
- Bit64u a0,
- Bit64u a1,
- Bit64u b0,
- Bit64u b1,
- Bit64u *z0Ptr,
- Bit64u *z1Ptr,
- Bit64u *z2Ptr,
- Bit64u *z3Ptr
-)
-{
- Bit64u z0, z1, z2, z3;
- Bit64u more1, more2;
-
- mul64To128(a1, b1, &z2, &z3);
- mul64To128(a1, b0, &z1, &more2);
- add128(z1, more2, 0, z2, &z1, &z2);
- mul64To128(a0, b0, &z0, &more1);
- add128(z0, more1, 0, z1, &z0, &z1);
- mul64To128(a0, b1, &more1, &more2);
- add128(more1, more2, 0, z2, &more1, &z2);
- add128(z0, z1, 0, more1, &z0, &z1);
- *z3Ptr = z3;
- *z2Ptr = z2;
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-
-/*----------------------------------------------------------------------------
-| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
-| by 64 _plus_ the number of bits given in `count'. The shifted result is
-| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
-| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
-| off form a third 64-bit result as follows: The _last_ bit shifted off is
-| the most-significant bit of the extra result, and the other 63 bits of the
-| extra result are all zero if and only if _all_but_the_last_ bits shifted off
-| were all zero. This extra result is stored in the location pointed to by
-| `z2Ptr'. The value of `count' can be arbitrarily large.
-| (This routine makes more sense if `a0', `a1', and `a2' are considered
-| to form a fixed-point value with binary point between `a1' and `a2'. This
-| fixed-point value is shifted right by the number of bits given in `count',
-| and the integer part of the result is returned at the locations pointed to
-| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
-| corrupted as described above, and is returned at the location pointed to by
-| `z2Ptr'.)
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void shift128ExtraRightJamming(
- Bit64u a0,
- Bit64u a1,
- Bit64u a2,
- int count,
- Bit64u *z0Ptr,
- Bit64u *z1Ptr,
- Bit64u *z2Ptr
-)
-{
- Bit64u z0, z1, z2;
- int negCount = (-count) & 63;
-
- if (count == 0) {
- z2 = a2;
- z1 = a1;
- z0 = a0;
- }
- else {
- if (count < 64) {
- z2 = a1<>count);
- z0 = a0>>count;
- }
- else {
- if (count == 64) {
- z2 = a1;
- z1 = a0;
- }
- else {
- a2 |= a1;
- if (count < 128) {
- z2 = a0<>(count & 63);
- }
- else {
- z2 = (count == 128) ? a0 : (a0 != 0);
- z1 = 0;
- }
- }
- z0 = 0;
- }
- z2 |= (a2 != 0);
- }
- *z2Ptr = z2;
- *z1Ptr = z1;
- *z0Ptr = z0;
-}
-
-#endif /* FLOAT128 */
-
-#endif
diff --git a/src/cpu/softfloat/softfloat-muladd.cc b/src/cpu/softfloat/softfloat-muladd.cc
deleted file mode 100644
index 7c9fec70ed..0000000000
--- a/src/cpu/softfloat/softfloat-muladd.cc
+++ /dev/null
@@ -1,558 +0,0 @@
-/*============================================================================
-This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * This code is based on QEMU patch by Peter Maydell
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "softfloat.h"
-#include "softfloat-round-pack.h"
-
-/*----------------------------------------------------------------------------
-| Primitive arithmetic functions, including multi-word arithmetic, and
-| division and square root approximations. (Can be specialized to target
-| if desired).
-*----------------------------------------------------------------------------*/
-#include "softfloat-macros.h"
-
-/*----------------------------------------------------------------------------
-| Functions and definitions to determine: (1) whether tininess for underflow
-| is detected before or after rounding by default, (2) what (if anything)
-| happens when exceptions are raised, (3) how signaling NaNs are distinguished
-| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
-| are propagated from function inputs to output. These details are target-
-| specific.
-*----------------------------------------------------------------------------*/
-#include "softfloat-specialize.h"
-
-/*----------------------------------------------------------------------------
-| Takes three single-precision floating-point values `a', `b' and `c', one of
-| which is a NaN, and returns the appropriate NaN result. If any of `a',
-| `b' or `c' is a signaling NaN, the invalid exception is raised.
-| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case
-| obviously c is a NaN, and whether to propagate c or some other NaN is
-| implementation defined).
-*----------------------------------------------------------------------------*/
-
-static float32 propagateFloat32MulAddNaN(float32 a, float32 b, float32 c, struct float_status_t *status)
-{
- int aIsNaN = float32_is_nan(a);
- int bIsNaN = float32_is_nan(b);
-
- int aIsSignalingNaN = float32_is_signaling_nan(a);
- int bIsSignalingNaN = float32_is_signaling_nan(b);
- int cIsSignalingNaN = float32_is_signaling_nan(c);
-
- a |= 0x00400000;
- b |= 0x00400000;
- c |= 0x00400000;
-
- if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN)
- float_raise(status, float_flag_invalid);
-
- // operate according to float_first_operand_nan mode
- if (aIsSignalingNaN | aIsNaN) {
- return a;
- }
- else {
- return (bIsSignalingNaN | bIsNaN) ? b : c;
- }
-}
-
-/*----------------------------------------------------------------------------
-| Takes three double-precision floating-point values `a', `b' and `c', one of
-| which is a NaN, and returns the appropriate NaN result. If any of `a',
-| `b' or `c' is a signaling NaN, the invalid exception is raised.
-| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case
-| obviously c is a NaN, and whether to propagate c or some other NaN is
-| implementation defined).
-*----------------------------------------------------------------------------*/
-
-static float64 propagateFloat64MulAddNaN(float64 a, float64 b, float64 c, struct float_status_t *status)
-{
- int aIsNaN = float64_is_nan(a);
- int bIsNaN = float64_is_nan(b);
-
- int aIsSignalingNaN = float64_is_signaling_nan(a);
- int bIsSignalingNaN = float64_is_signaling_nan(b);
- int cIsSignalingNaN = float64_is_signaling_nan(c);
-
- a |= BX_CONST64(0x0008000000000000);
- b |= BX_CONST64(0x0008000000000000);
- c |= BX_CONST64(0x0008000000000000);
-
- if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN)
- float_raise(status, float_flag_invalid);
-
- // operate according to float_first_operand_nan mode
- if (aIsSignalingNaN | aIsNaN) {
- return a;
- }
- else {
- return (bIsSignalingNaN | bIsNaN) ? b : c;
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the single-precision floating-point values
-| `a' and `b' then adding 'c', with no intermediate rounding step after the
-| multiplication. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic 754-2008.
-| The flags argument allows the caller to select negation of the
-| addend, the intermediate product, or the final result. (The difference
-| between this and having the caller do a separate negation is that negating
-| externally will flip the sign bit on NaNs.)
-*----------------------------------------------------------------------------*/
-
-float32 float32_muladd(float32 a, float32 b, float32 c, int flags, struct float_status_t *status)
-{
- int aSign, bSign, cSign, zSign;
- Bit16s aExp, bExp, cExp, pExp, zExp;
- Bit32u aSig, bSig, cSig;
- int pInf, pZero, pSign;
- Bit64u pSig64, cSig64, zSig64;
- Bit32u pSig;
- int shiftcount;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- bSig = extractFloat32Frac(b);
- bExp = extractFloat32Exp(b);
- bSign = extractFloat32Sign(b);
- cSig = extractFloat32Frac(c);
- cExp = extractFloat32Exp(c);
- cSign = extractFloat32Sign(c);
-
- /* It is implementation-defined whether the cases of (0,inf,qnan)
- * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
- * they return if they do), so we have to hand this information
- * off to the target-specific pick-a-NaN routine.
- */
- if (((aExp == 0xff) && aSig) ||
- ((bExp == 0xff) && bSig) ||
- ((cExp == 0xff) && cSig)) {
- return propagateFloat32MulAddNaN(a, b, c, status);
- }
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- if (cExp == 0) cSig = 0;
- }
-
- int infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) ||
- (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0));
-
- if (infzero) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
-
- if (flags & float_muladd_negate_c) {
- cSign ^= 1;
- }
-
- /* Work out the sign and type of the product */
- pSign = aSign ^ bSign;
- if (flags & float_muladd_negate_product) {
- pSign ^= 1;
- }
- pInf = (aExp == 0xff) || (bExp == 0xff);
- pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0);
-
- if (cExp == 0xff) {
- if (pInf && (pSign ^ cSign)) {
- /* addition of opposite-signed infinities => InvalidOperation */
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- /* Otherwise generate an infinity of the same sign */
- if ((aSig && aExp == 0) || (bSig && bExp == 0)) {
- float_raise(status, float_flag_denormal);
- }
- return packFloat32(cSign, 0xff, 0);
- }
-
- if (pInf) {
- if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) {
- float_raise(status, float_flag_denormal);
- }
- return packFloat32(pSign, 0xff, 0);
- }
-
- if (pZero) {
- if (cExp == 0) {
- if (cSig == 0) {
- /* Adding two exact zeroes */
- if (pSign == cSign) {
- zSign = pSign;
- } else if (get_float_rounding_mode(status) == float_round_down) {
- zSign = 1;
- } else {
- zSign = 0;
- }
- return packFloat32(zSign, 0, 0);
- }
- /* Exact zero plus a denormal */
- float_raise(status, float_flag_denormal);
- if (get_flush_underflow_to_zero(status)) {
- float_raise(status, float_flag_underflow | float_flag_inexact);
- return packFloat32(cSign, 0, 0);
- }
- }
- /* Zero plus something non-zero */
- return packFloat32(cSign, cExp, cSig);
- }
-
- if (aExp == 0) {
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(bSig, &bExp, &bSig);
- }
-
- /* Calculate the actual result a * b + c */
-
- /* Multiply first; this is easy. */
- /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f
- * because we want the true exponent, not the "one-less-than"
- * flavour that roundAndPackFloat32() takes.
- */
- pExp = aExp + bExp - 0x7e;
- aSig = (aSig | 0x00800000) << 7;
- bSig = (bSig | 0x00800000) << 8;
- pSig64 = (Bit64u)aSig * bSig;
- if ((Bit64s)(pSig64 << 1) >= 0) {
- pSig64 <<= 1;
- pExp--;
- }
-
- zSign = pSign;
-
- /* Now pSig64 is the significand of the multiply, with the explicit bit in
- * position 62.
- */
- if (cExp == 0) {
- if (!cSig) {
- /* Throw out the special case of c being an exact zero now */
- pSig = (Bit32u) shift64RightJamming(pSig64, 32);
- return roundAndPackFloat32(zSign, pExp - 1, pSig, status);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(cSig, &cExp, &cSig);
- }
-
- cSig64 = (Bit64u)cSig << 39;
- cSig64 |= BX_CONST64(0x4000000000000000);
- int expDiff = pExp - cExp;
-
- if (pSign == cSign) {
- /* Addition */
- if (expDiff > 0) {
- /* scale c to match p */
- cSig64 = shift64RightJamming(cSig64, expDiff);
- zExp = pExp;
- } else if (expDiff < 0) {
- /* scale p to match c */
- pSig64 = shift64RightJamming(pSig64, -expDiff);
- zExp = cExp;
- } else {
- /* no scaling needed */
- zExp = cExp;
- }
- /* Add significands and make sure explicit bit ends up in posn 62 */
- zSig64 = pSig64 + cSig64;
- if ((Bit64s)zSig64 < 0) {
- zSig64 = shift64RightJamming(zSig64, 1);
- } else {
- zExp--;
- }
- zSig64 = shift64RightJamming(zSig64, 32);
- return roundAndPackFloat32(zSign, zExp, zSig64, status);
- } else {
- /* Subtraction */
- if (expDiff > 0) {
- cSig64 = shift64RightJamming(cSig64, expDiff);
- zSig64 = pSig64 - cSig64;
- zExp = pExp;
- } else if (expDiff < 0) {
- pSig64 = shift64RightJamming(pSig64, -expDiff);
- zSig64 = cSig64 - pSig64;
- zExp = cExp;
- zSign ^= 1;
- } else {
- zExp = pExp;
- if (cSig64 < pSig64) {
- zSig64 = pSig64 - cSig64;
- } else if (pSig64 < cSig64) {
- zSig64 = cSig64 - pSig64;
- zSign ^= 1;
- } else {
- /* Exact zero */
- return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0);
- }
- }
- --zExp;
- /* Do the equivalent of normalizeRoundAndPackFloat32() but
- * starting with the significand in a Bit64u.
- */
- shiftcount = countLeadingZeros64(zSig64) - 1;
- zSig64 <<= shiftcount;
- zExp -= shiftcount;
- zSig64 = shift64RightJamming(zSig64, 32);
- return roundAndPackFloat32(zSign, zExp, zSig64, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the double-precision floating-point values
-| `a' and `b' then adding 'c', with no intermediate rounding step after the
-| multiplication. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic 754-2008.
-| The flags argument allows the caller to select negation of the
-| addend, the intermediate product, or the final result. (The difference
-| between this and having the caller do a separate negation is that negating
-| externally will flip the sign bit on NaNs.)
-*----------------------------------------------------------------------------*/
-
-float64 float64_muladd(float64 a, float64 b, float64 c, int flags, struct float_status_t *status)
-{
- int aSign, bSign, cSign, zSign;
- Bit16s aExp, bExp, cExp, pExp, zExp;
- Bit64u aSig, bSig, cSig;
- int pInf, pZero, pSign;
- Bit64u pSig0, pSig1, cSig0, cSig1, zSig0, zSig1;
- int shiftcount;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
- bSig = extractFloat64Frac(b);
- bExp = extractFloat64Exp(b);
- bSign = extractFloat64Sign(b);
- cSig = extractFloat64Frac(c);
- cExp = extractFloat64Exp(c);
- cSign = extractFloat64Sign(c);
-
- /* It is implementation-defined whether the cases of (0,inf,qnan)
- * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
- * they return if they do), so we have to hand this information
- * off to the target-specific pick-a-NaN routine.
- */
- if (((aExp == 0x7ff) && aSig) ||
- ((bExp == 0x7ff) && bSig) ||
- ((cExp == 0x7ff) && cSig)) {
- return propagateFloat64MulAddNaN(a, b, c, status);
- }
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- if (cExp == 0) cSig = 0;
- }
-
- int infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) ||
- (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0));
-
- if (infzero) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
-
- if (flags & float_muladd_negate_c) {
- cSign ^= 1;
- }
-
- /* Work out the sign and type of the product */
- pSign = aSign ^ bSign;
- if (flags & float_muladd_negate_product) {
- pSign ^= 1;
- }
- pInf = (aExp == 0x7ff) || (bExp == 0x7ff);
- pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0);
-
- if (cExp == 0x7ff) {
- if (pInf && (pSign ^ cSign)) {
- /* addition of opposite-signed infinities => InvalidOperation */
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- /* Otherwise generate an infinity of the same sign */
- if ((aSig && aExp == 0) || (bSig && bExp == 0)) {
- float_raise(status, float_flag_denormal);
- }
- return packFloat64(cSign, 0x7ff, 0);
- }
-
- if (pInf) {
- if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) {
- float_raise(status, float_flag_denormal);
- }
- return packFloat64(pSign, 0x7ff, 0);
- }
-
- if (pZero) {
- if (cExp == 0) {
- if (cSig == 0) {
- /* Adding two exact zeroes */
- if (pSign == cSign) {
- zSign = pSign;
- } else if (get_float_rounding_mode(status) == float_round_down) {
- zSign = 1;
- } else {
- zSign = 0;
- }
- return packFloat64(zSign, 0, 0);
- }
- /* Exact zero plus a denormal */
- float_raise(status, float_flag_denormal);
- if (get_flush_underflow_to_zero(status)) {
- float_raise(status, float_flag_underflow | float_flag_inexact);
- return packFloat64(cSign, 0, 0);
- }
- }
- /* Zero plus something non-zero */
- return packFloat64(cSign, cExp, cSig);
- }
-
- if (aExp == 0) {
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(bSig, &bExp, &bSig);
- }
-
- /* Calculate the actual result a * b + c */
-
- /* Multiply first; this is easy. */
- /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff
- * because we want the true exponent, not the "one-less-than"
- * flavour that roundAndPackFloat64() takes.
- */
- pExp = aExp + bExp - 0x3fe;
- aSig = (aSig | BX_CONST64(0x0010000000000000))<<10;
- bSig = (bSig | BX_CONST64(0x0010000000000000))<<11;
- mul64To128(aSig, bSig, &pSig0, &pSig1);
- if ((Bit64s)(pSig0 << 1) >= 0) {
- shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1);
- pExp--;
- }
-
- zSign = pSign;
-
- /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit
- * bit in position 126.
- */
- if (cExp == 0) {
- if (!cSig) {
- /* Throw out the special case of c being an exact zero now */
- shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1);
- return roundAndPackFloat64(zSign, pExp - 1, pSig1, status);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(cSig, &cExp, &cSig);
- }
-
- cSig0 = cSig << 10;
- cSig1 = 0;
- cSig0 |= BX_CONST64(0x4000000000000000);
- int expDiff = pExp - cExp;
-
- if (pSign == cSign) {
- /* Addition */
- if (expDiff > 0) {
- /* scale c to match p */
- shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1);
- zExp = pExp;
- } else if (expDiff < 0) {
- /* scale p to match c */
- shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1);
- zExp = cExp;
- } else {
- /* no scaling needed */
- zExp = cExp;
- }
- /* Add significands and make sure explicit bit ends up in posn 126 */
- add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
- if ((Bit64s)zSig0 < 0) {
- shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1);
- } else {
- zExp--;
- }
- shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1);
- return roundAndPackFloat64(zSign, zExp, zSig1, status);
- } else {
- /* Subtraction */
- if (expDiff > 0) {
- shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1);
- sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
- zExp = pExp;
- } else if (expDiff < 0) {
- shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1);
- sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1);
- zExp = cExp;
- zSign ^= 1;
- } else {
- zExp = pExp;
- if (lt128(cSig0, cSig1, pSig0, pSig1)) {
- sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
- } else if (lt128(pSig0, pSig1, cSig0, cSig1)) {
- sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1);
- zSign ^= 1;
- } else {
- /* Exact zero */
- return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0);
- }
- }
- --zExp;
- /* Do the equivalent of normalizeRoundAndPackFloat64() but
- * starting with the significand in a pair of Bit64u.
- */
- if (zSig0) {
- shiftcount = countLeadingZeros64(zSig0) - 1;
- shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1);
- if (zSig1) {
- zSig0 |= 1;
- }
- zExp -= shiftcount;
- } else {
- shiftcount = countLeadingZeros64(zSig1) - 1;
- zSig0 = zSig1 << shiftcount;
- zExp -= (shiftcount + 64);
- }
- return roundAndPackFloat64(zSign, zExp, zSig0, status);
- }
-}
diff --git a/src/cpu/softfloat/softfloat-round-pack.cc b/src/cpu/softfloat/softfloat-round-pack.cc
deleted file mode 100644
index 2b3965840c..0000000000
--- a/src/cpu/softfloat/softfloat-round-pack.cc
+++ /dev/null
@@ -1,896 +0,0 @@
-/*============================================================================
-This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-#define FLOAT128
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "softfloat.h"
-#include "softfloat-round-pack.h"
-
-/*----------------------------------------------------------------------------
-| Primitive arithmetic functions, including multi-word arithmetic, and
-| division and square root approximations. (Can be specialized to target
-| if desired).
-*----------------------------------------------------------------------------*/
-#include "softfloat-macros.h"
-
-/*----------------------------------------------------------------------------
-| Functions and definitions to determine: (1) whether tininess for underflow
-| is detected before or after rounding by default, (2) what (if anything)
-| happens when exceptions are raised, (3) how signaling NaNs are distinguished
-| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
-| are propagated from function inputs to output. These details are target-
-| specific.
-*----------------------------------------------------------------------------*/
-#include "softfloat-specialize.h"
-
-/*----------------------------------------------------------------------------
-| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
-| and 7, and returns the properly rounded 32-bit integer corresponding to the
-| input. If `zSign' is 1, the input is negated before being converted to an
-| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
-| is simply rounded to an integer, with the inexact exception raised if the
-| input cannot be represented exactly as an integer. However, if the fixed-
-| point input is too large, the invalid exception is raised and the integer
-| indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32s roundAndPackInt32(int zSign, Bit64u exactAbsZ, struct float_status_t *status)
-{
- int roundingMode = get_float_rounding_mode(status);
- int roundNearestEven = (roundingMode == float_round_nearest_even);
- int roundIncrement = 0x40;
- if (! roundNearestEven) {
- if (roundingMode == float_round_to_zero) roundIncrement = 0;
- else {
- roundIncrement = 0x7F;
- if (zSign) {
- if (roundingMode == float_round_up) roundIncrement = 0;
- }
- else {
- if (roundingMode == float_round_down) roundIncrement = 0;
- }
- }
- }
- int roundBits = (int)(exactAbsZ & 0x7F);
- Bit64u absZ = (exactAbsZ + roundIncrement)>>7;
- absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven);
- Bit32s z = (Bit32s) absZ;
- if (zSign) z = -z;
- if ((absZ>>32) || (z && ((z < 0) ^ zSign))) {
- float_raise(status, float_flag_invalid);
- return (Bit32s)(int32_indefinite);
- }
- if (roundBits) {
- float_raise(status, float_flag_inexact);
- if ((absZ << 7) > exactAbsZ)
- set_float_rounding_up(status);
- }
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
-| `absZ1', with binary point between bits 63 and 64 (between the input words),
-| and returns the properly rounded 64-bit integer corresponding to the input.
-| If `zSign' is 1, the input is negated before being converted to an integer.
-| Ordinarily, the fixed-point input is simply rounded to an integer, with
-| the inexact exception raised if the input cannot be represented exactly as
-| an integer. However, if the fixed-point input is too large, the invalid
-| exception is raised and the integer indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status)
-{
- Bit64s z;
- int roundingMode = get_float_rounding_mode(status);
- int roundNearestEven = (roundingMode == float_round_nearest_even);
- int increment = ((Bit64s) absZ1 < 0);
- if (! roundNearestEven) {
- if (roundingMode == float_round_to_zero) increment = 0;
- else {
- if (zSign) {
- increment = (roundingMode == float_round_down) && absZ1;
- }
- else {
- increment = (roundingMode == float_round_up) && absZ1;
- }
- }
- }
- Bit64u exactAbsZ0 = absZ0;
- if (increment) {
- ++absZ0;
- if (absZ0 == 0) goto overflow;
- absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven);
- }
- z = absZ0;
- if (zSign) z = -z;
- if (z && ((z < 0) ^ zSign)) {
- overflow:
- float_raise(status, float_flag_invalid);
- return (Bit64s)(int64_indefinite);
- }
- if (absZ1) {
- float_raise(status, float_flag_inexact);
- if (absZ0 > exactAbsZ0)
- set_float_rounding_up(status);
- }
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
-| `absZ1', with binary point between bits 63 and 64 (between the input words),
-| and returns the properly rounded 64-bit unsigned integer corresponding to the
-| input. Ordinarily, the fixed-point input is simply rounded to an integer,
-| with the inexact exception raised if the input cannot be represented exactly
-| as an integer. However, if the fixed-point input is too large, the invalid
-| exception is raised and the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status)
-{
- int roundingMode = get_float_rounding_mode(status);
- int roundNearestEven = (roundingMode == float_round_nearest_even);
- int increment = ((Bit64s) absZ1 < 0);
- if (!roundNearestEven) {
- if (roundingMode == float_round_to_zero) {
- increment = 0;
- } else if (absZ1) {
- if (zSign) {
- increment = (roundingMode == float_round_down) && absZ1;
- } else {
- increment = (roundingMode == float_round_up) && absZ1;
- }
- }
- }
- if (increment) {
- ++absZ0;
- if (absZ0 == 0) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
- absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven);
- }
-
- if (zSign && absZ0) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
-
- if (absZ1) {
- float_raise(status, float_flag_inexact);
- }
- return absZ0;
-}
-
-#ifdef FLOAT16
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal half-precision floating-point value represented
-| by the denormalized significand `aSig'. The normalized exponent and
-| significand are stored at the locations pointed to by `zExpPtr' and
-| `zSigPtr', respectively.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr)
-{
- int shiftCount = countLeadingZeros16(aSig) - 5;
- *zSigPtr = aSig<> 4;
- zSigRound &= ~(((roundBits ^ 0x10) == 0) & roundNearestEven);
- if (zSigRound == 0) zExp = 0;
- return packFloat16(zSign, zExp, zSigRound);
-}
-
-#endif
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal single-precision floating-point value represented
-| by the denormalized significand `aSig'. The normalized exponent and
-| significand are stored at the locations pointed to by `zExpPtr' and
-| `zSigPtr', respectively.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr)
-{
- int shiftCount = countLeadingZeros32(aSig) - 8;
- *zSigPtr = aSig<> 7;
- zSigRound &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven);
- if (zSigRound == 0) zExp = 0;
- if (roundBits) {
- float_raise(status, float_flag_inexact);
- if ((zSigRound << 7) > zSig) set_float_rounding_up(status);
- }
- return packFloat32(zSign, zExp, zSigRound);
-}
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper single-precision floating-
-| point value corresponding to the abstract input. This routine is just like
-| `roundAndPackFloat32' except that `zSig' does not have to be normalized.
-| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
-| floating-point exponent.
-*----------------------------------------------------------------------------*/
-
-float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status)
-{
- int shiftCount = countLeadingZeros32(zSig) - 1;
- return roundAndPackFloat32(zSign, zExp - shiftCount, zSig<>10;
- zSigRound &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven);
- if (zSigRound == 0) zExp = 0;
- if (roundBits) {
- float_raise(status, float_flag_inexact);
- if ((zSigRound << 10) > zSig) set_float_rounding_up(status);
- }
- return packFloat64(zSign, zExp, zSigRound);
-}
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper double-precision floating-
-| point value corresponding to the abstract input. This routine is just like
-| `roundAndPackFloat64' except that `zSig' does not have to be normalized.
-| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
-| floating-point exponent.
-*----------------------------------------------------------------------------*/
-
-float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status)
-{
- int shiftCount = countLeadingZeros64(zSig) - 1;
- return roundAndPackFloat64(zSign, zExp - shiftCount, zSig< zSigExact) set_float_rounding_up(status);
- }
- return packFloatx80(zSign, zExp, zSig0);
- }
- }
- if (roundBits) float_raise(status, float_flag_inexact);
- zSigExact = zSig0;
- zSig0 += roundIncrement;
- if (zSig0 < roundIncrement) {
- // Basically scale by shifting right and keep overflow
- ++zExp;
- zSig0 = BX_CONST64(0x8000000000000000);
- zSigExact >>= 1; // must scale also, or else later tests will fail
- }
- roundIncrement = roundMask + 1;
- if (roundNearestEven && (roundBits<<1 == roundIncrement))
- roundMask |= roundIncrement;
- zSig0 &= ~roundMask;
- if (zSig0 > zSigExact) set_float_rounding_up(status);
- if (zSig0 == 0) zExp = 0;
- return packFloatx80(zSign, zExp, zSig0);
- precision80:
- increment = ((Bit64s) zSig1 < 0);
- if (! roundNearestEven) {
- if (roundingMode == float_round_to_zero) increment = 0;
- else {
- if (zSign) {
- increment = (roundingMode == float_round_down) && zSig1;
- }
- else {
- increment = (roundingMode == float_round_up) && zSig1;
- }
- }
- }
- if (0x7FFD <= (Bit32u) (zExp - 1)) {
- if ((0x7FFE < zExp)
- || ((zExp == 0x7FFE)
- && (zSig0 == BX_CONST64(0xFFFFFFFFFFFFFFFF))
- && increment))
- {
- roundMask = 0;
- overflow:
- float_raise(status, float_flag_overflow | float_flag_inexact);
- if ((roundingMode == float_round_to_zero)
- || (zSign && (roundingMode == float_round_up))
- || (! zSign && (roundingMode == float_round_down)))
- {
- return packFloatx80(zSign, 0x7FFE, ~roundMask);
- }
- set_float_rounding_up(status);
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (zExp <= 0) {
- int isTiny = (zExp < 0) || (! increment)
- || (zSig0 < BX_CONST64(0xFFFFFFFFFFFFFFFF));
- shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1);
- zExp = 0;
- if (isTiny) {
- if (zSig1 || (zSig0 && !float_exception_masked(status, float_flag_underflow)))
- float_raise(status, float_flag_underflow);
- }
- if (zSig1) float_raise(status, float_flag_inexact);
- if (roundNearestEven) increment = ((Bit64s) zSig1 < 0);
- else {
- if (zSign) {
- increment = (roundingMode == float_round_down) && zSig1;
- } else {
- increment = (roundingMode == float_round_up) && zSig1;
- }
- }
- if (increment) {
- zSigExact = zSig0++;
- zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven);
- if (zSig0 > zSigExact) set_float_rounding_up(status);
- if ((Bit64s) zSig0 < 0) zExp = 1;
- }
- return packFloatx80(zSign, zExp, zSig0);
- }
- }
- if (zSig1) float_raise(status, float_flag_inexact);
- if (increment) {
- zSigExact = zSig0++;
- if (zSig0 == 0) {
- zExp++;
- zSig0 = BX_CONST64(0x8000000000000000);
- zSigExact >>= 1; // must scale also, or else later tests will fail
- }
- else {
- zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven);
- }
- if (zSig0 > zSigExact) set_float_rounding_up(status);
- }
- else {
- if (zSig0 == 0) zExp = 0;
- }
- return packFloatx80(zSign, zExp, zSig0);
-}
-
-floatx80 roundAndPackFloatx80(int roundingPrecision,
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
-{
- struct float_status_t *round_status = status;
- floatx80 result = SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status);
-
- // bias unmasked undeflow
- if (status->float_exception_flags & ~status->float_exception_masks & float_flag_underflow) {
- float_raise(round_status, float_flag_underflow);
- return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp + 0x6000, zSig0, zSig1, status = round_status);
- }
-
- // bias unmasked overflow
- if (status->float_exception_flags & ~status->float_exception_masks & float_flag_overflow) {
- float_raise(round_status, float_flag_overflow);
- return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp - 0x6000, zSig0, zSig1, status = round_status);
- }
-
- return result;
-}
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent
-| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
-| and returns the proper extended double-precision floating-point value
-| corresponding to the abstract input. This routine is just like
-| `roundAndPackFloatx80' except that the input significand does not have to be
-| normalized.
-*----------------------------------------------------------------------------*/
-
-floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision,
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
-{
- if (zSig0 == 0) {
- zSig0 = zSig1;
- zSig1 = 0;
- zExp -= 64;
- }
- int shiftCount = countLeadingZeros64(zSig0);
- shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
- zExp -= shiftCount;
- return
- roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status);
-}
-
-#endif
-
-#ifdef FLOAT128
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal quadruple-precision floating-point value
-| represented by the denormalized significand formed by the concatenation of
-| `aSig0' and `aSig1'. The normalized exponent is stored at the location
-| pointed to by `zExpPtr'. The most significant 49 bits of the normalized
-| significand are stored at the location pointed to by `zSig0Ptr', and the
-| least significant 64 bits of the normalized significand are stored at the
-| location pointed to by `zSig1Ptr'.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat128Subnormal(
- Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr)
-{
- int shiftCount;
-
- if (aSig0 == 0) {
- shiftCount = countLeadingZeros64(aSig1) - 15;
- if (shiftCount < 0) {
- *zSig0Ptr = aSig1 >>(-shiftCount);
- *zSig1Ptr = aSig1 << (shiftCount & 63);
- }
- else {
- *zSig0Ptr = aSig1 << shiftCount;
- *zSig1Ptr = 0;
- }
- *zExpPtr = - shiftCount - 63;
- }
- else {
- shiftCount = countLeadingZeros64(aSig0) - 15;
- shortShift128Left(aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr);
- *zExpPtr = 1 - shiftCount;
- }
-}
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and extended significand formed by the concatenation of `zSig0', `zSig1',
-| and `zSig2', and returns the proper quadruple-precision floating-point value
-| corresponding to the abstract input. Ordinarily, the abstract value is
-| simply rounded and packed into the quadruple-precision format, with the
-| inexact exception raised if the abstract input cannot be represented
-| exactly. However, if the abstract value is too large, the overflow and
-| inexact exceptions are raised and an infinity or maximal finite value is
-| returned. If the abstract value is too small, the input value is rounded to
-| a subnormal number, and the underflow and inexact exceptions are raised if
-| the abstract input cannot be represented exactly as a subnormal quadruple-
-| precision floating-point number.
-| The input significand must be normalized or smaller. If the input
-| significand is not normalized, `zExp' must be 0; in that case, the result
-| returned is a subnormal number, and it must not require rounding. In the
-| usual case that the input significand is normalized, `zExp' must be 1 less
-| than the ``true'' floating-point exponent. The handling of underflow and
-| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 roundAndPackFloat128(
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status)
-{
- int increment = ((Bit64s) zSig2 < 0);
- if (0x7FFD <= (Bit32u) zExp) {
- if ((0x7FFD < zExp)
- || ((zExp == 0x7FFD)
- && eq128(BX_CONST64(0x0001FFFFFFFFFFFF),
- BX_CONST64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1)
- && increment))
- {
- float_raise(status, float_flag_overflow | float_flag_inexact);
- return packFloat128Four(zSign, 0x7FFF, 0, 0);
- }
- if (zExp < 0) {
- int isTiny = (zExp < -1)
- || ! increment
- || lt128(zSig0, zSig1,
- BX_CONST64(0x0001FFFFFFFFFFFF),
- BX_CONST64(0xFFFFFFFFFFFFFFFF));
- shift128ExtraRightJamming(
- zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2);
- zExp = 0;
- if (isTiny && zSig2) float_raise(status, float_flag_underflow);
- increment = ((Bit64s) zSig2 < 0);
- }
- }
- if (zSig2) float_raise(status, float_flag_inexact);
- if (increment) {
- add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1);
- zSig1 &= ~((zSig2 + zSig2 == 0) & 1);
- }
- else {
- if ((zSig0 | zSig1) == 0) zExp = 0;
- }
- return packFloat128Four(zSign, zExp, zSig0, zSig1);
-}
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand formed by the concatenation of `zSig0' and `zSig1', and
-| returns the proper quadruple-precision floating-point value corresponding
-| to the abstract input. This routine is just like `roundAndPackFloat128'
-| except that the input significand has fewer bits and does not have to be
-| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
-| point exponent.
-*----------------------------------------------------------------------------*/
-
-float128 normalizeRoundAndPackFloat128(
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
-{
- Bit64u zSig2;
-
- if (zSig0 == 0) {
- zSig0 = zSig1;
- zSig1 = 0;
- zExp -= 64;
- }
- int shiftCount = countLeadingZeros64(zSig0) - 15;
- if (0 <= shiftCount) {
- zSig2 = 0;
- shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
- }
- else {
- shift128ExtraRightJamming(
- zSig0, zSig1, 0, -shiftCount, &zSig0, &zSig1, &zSig2);
- }
- zExp -= shiftCount;
- return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status);
-}
-
-#endif
diff --git a/src/cpu/softfloat/softfloat-round-pack.h b/src/cpu/softfloat/softfloat-round-pack.h
deleted file mode 100644
index 1422aaea60..0000000000
--- a/src/cpu/softfloat/softfloat-round-pack.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/*============================================================================
-This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#ifndef _SOFTFLOAT_ROUND_PACK_H_
-#define _SOFTFLOAT_ROUND_PACK_H_
-
-#include "softfloat.h"
-
-/*----------------------------------------------------------------------------
-| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
-| and 7, and returns the properly rounded 32-bit integer corresponding to the
-| input. If `zSign' is 1, the input is negated before being converted to an
-| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
-| is simply rounded to an integer, with the inexact exception raised if the
-| input cannot be represented exactly as an integer. However, if the fixed-
-| point input is too large, the invalid exception is raised and the integer
-| indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32s roundAndPackInt32(int zSign, Bit64u absZ, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
-| `absZ1', with binary point between bits 63 and 64 (between the input words),
-| and returns the properly rounded 64-bit integer corresponding to the input.
-| If `zSign' is 1, the input is negated before being converted to an integer.
-| Ordinarily, the fixed-point input is simply rounded to an integer, with
-| the inexact exception raised if the input cannot be represented exactly as
-| an integer. However, if the fixed-point input is too large, the invalid
-| exception is raised and the integer indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
-| `absZ1', with binary point between bits 63 and 64 (between the input words),
-| and returns the properly rounded 64-bit unsigned integer corresponding to the
-| input. Ordinarily, the fixed-point input is simply rounded to an integer,
-| with the inexact exception raised if the input cannot be represented exactly
-| as an integer. However, if the fixed-point input is too large, the invalid
-| exception is raised and the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status);
-
-#ifdef FLOAT16
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal half-precision floating-point value represented
-| by the denormalized significand `aSig'. The normalized exponent and
-| significand are stored at the locations pointed to by `zExpPtr' and
-| `zSigPtr', respectively.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper half-precision floating-
-| point value corresponding to the abstract input. Ordinarily, the abstract
-| value is simply rounded and packed into the half-precision format, with
-| the inexact exception raised if the abstract input cannot be represented
-| exactly. However, if the abstract value is too large, the overflow and
-| inexact exceptions are raised and an infinity or maximal finite value is
-| returned. If the abstract value is too small, the input value is rounded to
-| a subnormal number, and the underflow and inexact exceptions are raised if
-| the abstract input cannot be represented exactly as a subnormal single-
-| precision floating-point number.
-| The input significand `zSig' has its binary point between bits 14
-| and 13, which is 4 bits to the left of the usual location. This shifted
-| significand must be normalized or smaller. If `zSig' is not normalized,
-| `zExp' must be 0; in that case, the result returned is a subnormal number,
-| and it must not require rounding. In the usual case that `zSig' is
-| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
-| The handling of underflow and overflow follows the IEC/IEEE Standard for
-| Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float16 roundAndPackFloat16(int zSign, Bit16s zExp, Bit16u zSig, struct float_status_t *status);
-
-#endif
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal single-precision floating-point value represented
-| by the denormalized significand `aSig'. The normalized exponent and
-| significand are stored at the locations pointed to by `zExpPtr' and
-| `zSigPtr', respectively.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper single-precision floating-
-| point value corresponding to the abstract input. Ordinarily, the abstract
-| value is simply rounded and packed into the single-precision format, with
-| the inexact exception raised if the abstract input cannot be represented
-| exactly. However, if the abstract value is too large, the overflow and
-| inexact exceptions are raised and an infinity or maximal finite value is
-| returned. If the abstract value is too small, the input value is rounded to
-| a subnormal number, and the underflow and inexact exceptions are raised if
-| the abstract input cannot be represented exactly as a subnormal single-
-| precision floating-point number.
-| The input significand `zSig' has its binary point between bits 30
-| and 29, which is 7 bits to the left of the usual location. This shifted
-| significand must be normalized or smaller. If `zSig' is not normalized,
-| `zExp' must be 0; in that case, the result returned is a subnormal number,
-| and it must not require rounding. In the usual case that `zSig' is
-| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
-| The handling of underflow and overflow follows the IEC/IEEE Standard for
-| Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 roundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper single-precision floating-
-| point value corresponding to the abstract input. This routine is just like
-| `roundAndPackFloat32' except that `zSig' does not have to be normalized.
-| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
-| floating-point exponent.
-*----------------------------------------------------------------------------*/
-
-float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal double-precision floating-point value represented
-| by the denormalized significand `aSig'. The normalized exponent and
-| significand are stored at the locations pointed to by `zExpPtr' and
-| `zSigPtr', respectively.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat64Subnormal(Bit64u aSig, Bit16s *zExpPtr, Bit64u *zSigPtr);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper double-precision floating-
-| point value corresponding to the abstract input. Ordinarily, the abstract
-| value is simply rounded and packed into the double-precision format, with
-| the inexact exception raised if the abstract input cannot be represented
-| exactly. However, if the abstract value is too large, the overflow and
-| inexact exceptions are raised and an infinity or maximal finite value is
-| returned. If the abstract value is too small, the input value is rounded
-| to a subnormal number, and the underflow and inexact exceptions are raised
-| if the abstract input cannot be represented exactly as a subnormal double-
-| precision floating-point number.
-| The input significand `zSig' has its binary point between bits 62
-| and 61, which is 10 bits to the left of the usual location. This shifted
-| significand must be normalized or smaller. If `zSig' is not normalized,
-| `zExp' must be 0; in that case, the result returned is a subnormal number,
-| and it must not require rounding. In the usual case that `zSig' is
-| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
-| The handling of underflow and overflow follows the IEC/IEEE Standard for
-| Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 roundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand `zSig', and returns the proper double-precision floating-
-| point value corresponding to the abstract input. This routine is just like
-| `roundAndPackFloat64' except that `zSig' does not have to be normalized.
-| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
-| floating-point exponent.
-*----------------------------------------------------------------------------*/
-
-float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status);
-
-#ifdef FLOATX80
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal extended double-precision floating-point value
-| represented by the denormalized significand `aSig'. The normalized exponent
-| and significand are stored at the locations pointed to by `zExpPtr' and
-| `zSigPtr', respectively.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and extended significand formed by the concatenation of `zSig0' and `zSig1',
-| and returns the proper extended double-precision floating-point value
-| corresponding to the abstract input. Ordinarily, the abstract value is
-| rounded and packed into the extended double-precision format, with the
-| inexact exception raised if the abstract input cannot be represented
-| exactly. However, if the abstract value is too large, the overflow and
-| inexact exceptions are raised and an infinity or maximal finite value is
-| returned. If the abstract value is too small, the input value is rounded to
-| a subnormal number, and the underflow and inexact exceptions are raised if
-| the abstract input cannot be represented exactly as a subnormal extended
-| double-precision floating-point number.
-| If `roundingPrecision' is 32 or 64, the result is rounded to the same
-| number of bits as single or double precision, respectively. Otherwise, the
-| result is rounded to the full precision of the extended double-precision
-| format.
-| The input significand must be normalized or smaller. If the input
-| significand is not normalized, `zExp' must be 0; in that case, the result
-| returned is a subnormal number, and it must not require rounding. The
-| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 roundAndPackFloatx80(int roundingPrecision,
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent
-| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
-| and returns the proper extended double-precision floating-point value
-| corresponding to the abstract input. This routine is just like
-| `roundAndPackFloatx80' except that the input significand does not have to be
-| normalized.
-*----------------------------------------------------------------------------*/
-
-floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision,
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status);
-
-#endif // FLOATX80
-
-#ifdef FLOAT128
-
-/*----------------------------------------------------------------------------
-| Normalizes the subnormal quadruple-precision floating-point value
-| represented by the denormalized significand formed by the concatenation of
-| `aSig0' and `aSig1'. The normalized exponent is stored at the location
-| pointed to by `zExpPtr'. The most significant 49 bits of the normalized
-| significand are stored at the location pointed to by `zSig0Ptr', and the
-| least significant 64 bits of the normalized significand are stored at the
-| location pointed to by `zSig1Ptr'.
-*----------------------------------------------------------------------------*/
-
-void normalizeFloat128Subnormal(
- Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and extended significand formed by the concatenation of `zSig0', `zSig1',
-| and `zSig2', and returns the proper quadruple-precision floating-point value
-| corresponding to the abstract input. Ordinarily, the abstract value is
-| simply rounded and packed into the quadruple-precision format, with the
-| inexact exception raised if the abstract input cannot be represented
-| exactly. However, if the abstract value is too large, the overflow and
-| inexact exceptions are raised and an infinity or maximal finite value is
-| returned. If the abstract value is too small, the input value is rounded to
-| a subnormal number, and the underflow and inexact exceptions are raised if
-| the abstract input cannot be represented exactly as a subnormal quadruple-
-| precision floating-point number.
-| The input significand must be normalized or smaller. If the input
-| significand is not normalized, `zExp' must be 0; in that case, the result
-| returned is a subnormal number, and it must not require rounding. In the
-| usual case that the input significand is normalized, `zExp' must be 1 less
-| than the ``true'' floating-point exponent. The handling of underflow and
-| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 roundAndPackFloat128(
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
-| and significand formed by the concatenation of `zSig0' and `zSig1', and
-| returns the proper quadruple-precision floating-point value corresponding
-| to the abstract input. This routine is just like `roundAndPackFloat128'
-| except that the input significand has fewer bits and does not have to be
-| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
-| point exponent.
-*----------------------------------------------------------------------------*/
-
-float128 normalizeRoundAndPackFloat128(
- int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status);
-
-#endif // FLOAT128
-
-#endif
diff --git a/src/cpu/softfloat/softfloat-specialize.cc b/src/cpu/softfloat/softfloat-specialize.cc
deleted file mode 100644
index bf0d111446..0000000000
--- a/src/cpu/softfloat/softfloat-specialize.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-/*============================================================================
-This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
-Arithmetic Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-#define FLOAT128
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "softfloat.h"
-#include "softfloat-specialize.h"
-
-/*----------------------------------------------------------------------------
-| Takes two single-precision floating-point values `a' and `b', one of which
-| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
-| signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status)
-{
- int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
-
- aIsNaN = float32_is_nan(a);
- aIsSignalingNaN = float32_is_signaling_nan(a);
- bIsNaN = float32_is_nan(b);
- bIsSignalingNaN = float32_is_signaling_nan(b);
- a |= 0x00400000;
- b |= 0x00400000;
- if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
- if (get_float_nan_handling_mode(status) == float_larger_significand_nan) {
- if (aIsSignalingNaN) {
- if (bIsSignalingNaN) goto returnLargerSignificand;
- return bIsNaN ? b : a;
- }
- else if (aIsNaN) {
- if (bIsSignalingNaN | ! bIsNaN) return a;
- returnLargerSignificand:
- if ((Bit32u) (a<<1) < (Bit32u) (b<<1)) return b;
- if ((Bit32u) (b<<1) < (Bit32u) (a<<1)) return a;
- return (a < b) ? a : b;
- }
- else {
- return b;
- }
- } else {
- return (aIsSignalingNaN | aIsNaN) ? a : b;
- }
-}
-
-/*----------------------------------------------------------------------------
-| Takes two double-precision floating-point values `a' and `b', one of which
-| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
-| signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status)
-{
- int aIsNaN = float64_is_nan(a);
- int aIsSignalingNaN = float64_is_signaling_nan(a);
- int bIsNaN = float64_is_nan(b);
- int bIsSignalingNaN = float64_is_signaling_nan(b);
- a |= BX_CONST64(0x0008000000000000);
- b |= BX_CONST64(0x0008000000000000);
- if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
- if (get_float_nan_handling_mode(status) == float_larger_significand_nan) {
- if (aIsSignalingNaN) {
- if (bIsSignalingNaN) goto returnLargerSignificand;
- return bIsNaN ? b : a;
- }
- else if (aIsNaN) {
- if (bIsSignalingNaN | ! bIsNaN) return a;
- returnLargerSignificand:
- if ((Bit64u) (a<<1) < (Bit64u) (b<<1)) return b;
- if ((Bit64u) (b<<1) < (Bit64u) (a<<1)) return a;
- return (a < b) ? a : b;
- }
- else {
- return b;
- }
- } else {
- return (aIsSignalingNaN | aIsNaN) ? a : b;
- }
-}
-
-#ifdef FLOATX80
-
-/*----------------------------------------------------------------------------
-| Takes two extended double-precision floating-point values `a' and `b', one
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
-| `b' is a signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status)
-{
- int aIsNaN = floatx80_is_nan(a);
- int aIsSignalingNaN = floatx80_is_signaling_nan(a);
- int bIsNaN = floatx80_is_nan(b);
- int bIsSignalingNaN = floatx80_is_signaling_nan(b);
- a.fraction |= BX_CONST64(0xC000000000000000);
- b.fraction |= BX_CONST64(0xC000000000000000);
- if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
- if (aIsSignalingNaN) {
- if (bIsSignalingNaN) goto returnLargerSignificand;
- return bIsNaN ? b : a;
- }
- else if (aIsNaN) {
- if (bIsSignalingNaN | ! bIsNaN) return a;
- returnLargerSignificand:
- if (a.fraction < b.fraction) return b;
- if (b.fraction < a.fraction) return a;
- return (a.exp < b.exp) ? a : b;
- }
- else {
- return b;
- }
-}
-
-#endif /* FLOATX80 */
-
-#ifdef FLOAT128
-
-/*----------------------------------------------------------------------------
-| Takes two quadruple-precision floating-point values `a' and `b', one of
-| which is a NaN, and returns the appropriate NaN result. If either `a' or
-| `b' is a signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status)
-{
- int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
- aIsNaN = float128_is_nan(a);
- aIsSignalingNaN = float128_is_signaling_nan(a);
- bIsNaN = float128_is_nan(b);
- bIsSignalingNaN = float128_is_signaling_nan(b);
- a.hi |= BX_CONST64(0x0000800000000000);
- b.hi |= BX_CONST64(0x0000800000000000);
- if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
- if (aIsSignalingNaN) {
- if (bIsSignalingNaN) goto returnLargerSignificand;
- return bIsNaN ? b : a;
- }
- else if (aIsNaN) {
- if (bIsSignalingNaN | !bIsNaN) return a;
- returnLargerSignificand:
- if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b;
- if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a;
- return (a.hi < b.hi) ? a : b;
- }
- else {
- return b;
- }
-}
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN.
-*----------------------------------------------------------------------------*/
-const float128 float128_default_nan =
- packFloat128(float128_default_nan_hi, float128_default_nan_lo);
-
-#endif /* FLOAT128 */
diff --git a/src/cpu/softfloat/softfloat-specialize.h b/src/cpu/softfloat/softfloat-specialize.h
deleted file mode 100644
index 302ce53e43..0000000000
--- a/src/cpu/softfloat/softfloat-specialize.h
+++ /dev/null
@@ -1,789 +0,0 @@
-/*============================================================================
-This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
-Arithmetic Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-#ifndef _SOFTFLOAT_SPECIALIZE_H_
-#define _SOFTFLOAT_SPECIALIZE_H_
-
-#include "softfloat.h"
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#define int16_indefinite ((Bit16s)0x8000)
-#define int32_indefinite ((Bit32s)0x80000000)
-#define int64_indefinite BX_CONST64(0x8000000000000000)
-
-#define uint16_indefinite (0xffff)
-#define uint32_indefinite (0xffffffff)
-#define uint64_indefinite BX_CONST64(0xffffffffffffffff)
-
-/*----------------------------------------------------------------------------
-| Internal canonical NaN format.
-*----------------------------------------------------------------------------*/
-
-typedef struct {
- int sign;
- Bit64u hi, lo;
-} commonNaNT;
-
-#ifdef FLOAT16
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated half-precision NaN.
-*----------------------------------------------------------------------------*/
-extern const float16 float16_default_nan;
-
-#define float16_fraction extractFloat16Frac
-#define float16_exp extractFloat16Exp
-#define float16_sign extractFloat16Sign
-
-/*----------------------------------------------------------------------------
-| Returns the fraction bits of the half-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit16u extractFloat16Frac(float16 a)
-{
- return a & 0x3FF;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the exponent bits of the half-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit16s extractFloat16Exp(float16 a)
-{
- return (a>>10) & 0x1F;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the sign bit of the half-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int extractFloat16Sign(float16 a)
-{
- return a>>15;
-}
-
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
-| single-precision floating-point value, returning the result. After being
-| shifted into the proper positions, the three fields are simply added
-| together to form the result. This means that any integer portion of `zSig'
-| will be added into the exponent. Since a properly normalized significand
-| will have an integer portion equal to 1, the `zExp' input should be 1 less
-| than the desired result exponent whenever `zSig' is a complete, normalized
-| significand.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float16 packFloat16(int zSign, int zExp, Bit16u zSig)
-{
- return (((Bit16u) zSign)<<15) + (((Bit16u) zExp)<<10) + zSig;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the half-precision floating-point value `a' is a NaN;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float16_is_nan(float16 a)
-{
- return (0xF800 < (Bit16u) (a<<1));
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the half-precision floating-point value `a' is a signaling
-| NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float16_is_signaling_nan(float16 a)
-{
- return (((a>>9) & 0x3F) == 0x3E) && (a & 0x1FF);
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the half-precision floating-point value `a' is denormal;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float16_is_denormal(float16 a)
-{
- return (extractFloat16Exp(a) == 0) && (extractFloat16Frac(a) != 0);
-}
-
-/*----------------------------------------------------------------------------
-| Convert float16 denormals to zero.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float16 float16_denormal_to_zero(float16 a)
-{
- if (float16_is_denormal(a)) a &= 0x8000;
- return a;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the half-precision floating-point NaN
-| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
-| exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE commonNaNT float16ToCommonNaN(float16 a, struct float_status_t *status)
-{
- commonNaNT z;
- if (float16_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
- z.sign = a>>15;
- z.lo = 0;
- z.hi = ((Bit64u) a)<<54;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the canonical NaN `a' to the half-
-| precision floating-point format.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float16 commonNaNToFloat16(commonNaNT a)
-{
- return (((Bit16u) a.sign)<<15) | 0x7E00 | (Bit16u)(a.hi>>54);
-}
-
-#endif
-
-/*----------------------------------------------------------------------------
-| Commonly used single-precision floating point constants
-*----------------------------------------------------------------------------*/
-extern const float32 float32_negative_inf;
-extern const float32 float32_positive_inf;
-extern const float32 float32_negative_zero;
-extern const float32 float32_positive_zero;
-extern const float32 float32_negative_one;
-extern const float32 float32_positive_one;
-extern const float32 float32_max_float;
-extern const float32 float32_min_float;
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated single-precision NaN.
-*----------------------------------------------------------------------------*/
-extern const float32 float32_default_nan;
-
-#define float32_fraction extractFloat32Frac
-#define float32_exp extractFloat32Exp
-#define float32_sign extractFloat32Sign
-
-#define FLOAT32_EXP_BIAS 0x7F
-
-/*----------------------------------------------------------------------------
-| Returns the fraction bits of the single-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit32u extractFloat32Frac(float32 a)
-{
- return a & 0x007FFFFF;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the exponent bits of the single-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit16s extractFloat32Exp(float32 a)
-{
- return (a>>23) & 0xFF;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the sign bit of the single-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int extractFloat32Sign(float32 a)
-{
- return a>>31;
-}
-
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
-| single-precision floating-point value, returning the result. After being
-| shifted into the proper positions, the three fields are simply added
-| together to form the result. This means that any integer portion of `zSig'
-| will be added into the exponent. Since a properly normalized significand
-| will have an integer portion equal to 1, the `zExp' input should be 1 less
-| than the desired result exponent whenever `zSig' is a complete, normalized
-| significand.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float32 packFloat32(int zSign, Bit16s zExp, Bit32u zSig)
-{
- return (((Bit32u) zSign)<<31) + (((Bit32u) zExp)<<23) + zSig;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is a NaN;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float32_is_nan(float32 a)
-{
- return (0xFF000000 < (Bit32u) (a<<1));
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is a signaling
-| NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float32_is_signaling_nan(float32 a)
-{
- return (((a>>22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the single-precision floating-point value `a' is denormal;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float32_is_denormal(float32 a)
-{
- return (extractFloat32Exp(a) == 0) && (extractFloat32Frac(a) != 0);
-}
-
-/*----------------------------------------------------------------------------
-| Convert float32 denormals to zero.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float32 float32_denormal_to_zero(float32 a)
-{
- if (float32_is_denormal(a)) a &= 0x80000000;
- return a;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point NaN
-| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
-| exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE commonNaNT float32ToCommonNaN(float32 a, struct float_status_t *status)
-{
- commonNaNT z;
- if (float32_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
- z.sign = a>>31;
- z.lo = 0;
- z.hi = ((Bit64u) a)<<41;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the canonical NaN `a' to the single-
-| precision floating-point format.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float32 commonNaNToFloat32(commonNaNT a)
-{
- return (((Bit32u) a.sign)<<31) | 0x7FC00000 | (Bit32u)(a.hi>>41);
-}
-
-/*----------------------------------------------------------------------------
-| Takes two single-precision floating-point values `a' and `b', one of which
-| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
-| signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes single-precision floating-point NaN `a' and returns the appropriate
-| NaN result. If `a' is a signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float32 propagateFloat32NaNOne(float32 a, struct float_status_t *status)
-{
- if (float32_is_signaling_nan(a))
- float_raise(status, float_flag_invalid);
-
- return a | 0x00400000;
-}
-
-/*----------------------------------------------------------------------------
-| Commonly used single-precision floating point constants
-*----------------------------------------------------------------------------*/
-extern const float64 float64_negative_inf;
-extern const float64 float64_positive_inf;
-extern const float64 float64_negative_zero;
-extern const float64 float64_positive_zero;
-extern const float64 float64_negative_one;
-extern const float64 float64_positive_one;
-extern const float64 float64_max_float;
-extern const float64 float64_min_float;
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated double-precision NaN.
-*----------------------------------------------------------------------------*/
-extern const float64 float64_default_nan;
-
-#define float64_fraction extractFloat64Frac
-#define float64_exp extractFloat64Exp
-#define float64_sign extractFloat64Sign
-
-#define FLOAT64_EXP_BIAS 0x3FF
-
-/*----------------------------------------------------------------------------
-| Returns the fraction bits of the double-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit64u extractFloat64Frac(float64 a)
-{
- return a & BX_CONST64(0x000FFFFFFFFFFFFF);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the exponent bits of the double-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit16s extractFloat64Exp(float64 a)
-{
- return (Bit16s)(a>>52) & 0x7FF;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the sign bit of the double-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int extractFloat64Sign(float64 a)
-{
- return (int)(a>>63);
-}
-
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
-| double-precision floating-point value, returning the result. After being
-| shifted into the proper positions, the three fields are simply added
-| together to form the result. This means that any integer portion of `zSig'
-| will be added into the exponent. Since a properly normalized significand
-| will have an integer portion equal to 1, the `zExp' input should be 1 less
-| than the desired result exponent whenever `zSig' is a complete, normalized
-| significand.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float64 packFloat64(int zSign, Bit16s zExp, Bit64u zSig)
-{
- return (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<52) + zSig;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is a NaN;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float64_is_nan(float64 a)
-{
- return (BX_CONST64(0xFFE0000000000000) < (Bit64u) (a<<1));
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is a signaling
-| NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float64_is_signaling_nan(float64 a)
-{
- return (((a>>51) & 0xFFF) == 0xFFE) && (a & BX_CONST64(0x0007FFFFFFFFFFFF));
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the double-precision floating-point value `a' is denormal;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float64_is_denormal(float64 a)
-{
- return (extractFloat64Exp(a) == 0) && (extractFloat64Frac(a) != 0);
-}
-
-/*----------------------------------------------------------------------------
-| Convert float64 denormals to zero.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float64 float64_denormal_to_zero(float64 a)
-{
- if (float64_is_denormal(a)) a &= ((Bit64u)(1) << 63);
- return a;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point NaN
-| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
-| exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE commonNaNT float64ToCommonNaN(float64 a, struct float_status_t *status)
-{
- commonNaNT z;
- if (float64_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
- z.sign = (int)(a>>63);
- z.lo = 0;
- z.hi = a<<12;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the canonical NaN `a' to the double-
-| precision floating-point format.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a)
-{
- return (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FF8000000000000) | (a.hi>>12);
-}
-
-/*----------------------------------------------------------------------------
-| Takes two double-precision floating-point values `a' and `b', one of which
-| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
-| signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes double-precision floating-point NaN `a' and returns the appropriate
-| NaN result. If `a' is a signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float64 propagateFloat64NaNOne(float64 a, struct float_status_t *status)
-{
- if (float64_is_signaling_nan(a))
- float_raise(status, float_flag_invalid);
-
- return a | BX_CONST64(0x0008000000000000);
-}
-
-#ifdef FLOATX80
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN. The
-| `high' and `low' values hold the most- and least-significant bits,
-| respectively.
-*----------------------------------------------------------------------------*/
-#define floatx80_default_nan_exp 0xFFFF
-#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000)
-
-#define floatx80_fraction extractFloatx80Frac
-#define floatx80_exp extractFloatx80Exp
-#define floatx80_sign extractFloatx80Sign
-
-#define FLOATX80_EXP_BIAS 0x3FFF
-
-/*----------------------------------------------------------------------------
-| Returns the fraction bits of the extended double-precision floating-point
-| value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit64u extractFloatx80Frac(floatx80 a)
-{
- return a.fraction;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the exponent bits of the extended double-precision floating-point
-| value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit32s extractFloatx80Exp(floatx80 a)
-{
- return a.exp & 0x7FFF;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the sign bit of the extended double-precision floating-point value
-| `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int extractFloatx80Sign(floatx80 a)
-{
- return a.exp>>15;
-}
-
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
-| extended double-precision floating-point value, returning the result.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE floatx80 packFloatx80(int zSign, Bit32s zExp, Bit64u zSig)
-{
- floatx80 z;
- z.fraction = zSig;
- z.exp = (zSign << 15) + zExp;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is a
-| NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int floatx80_is_nan(floatx80 a)
-{
- // return ((a.exp & 0x7FFF) == 0x7FFF) && (Bit64s) (a.fraction<<1);
- return ((a.exp & 0x7FFF) == 0x7FFF) && (((Bit64s) (a.fraction<<1)) != 0);
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is a
-| signaling NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int floatx80_is_signaling_nan(floatx80 a)
-{
- Bit64u aLow = a.fraction & ~BX_CONST64(0x4000000000000000);
- return ((a.exp & 0x7FFF) == 0x7FFF) &&
- ((Bit64u) (aLow<<1)) && (a.fraction == aLow);
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the extended double-precision floating-point value `a' is an
-| unsupported; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int floatx80_is_unsupported(floatx80 a)
-{
- return ((a.exp & 0x7FFF) && !(a.fraction & BX_CONST64(0x8000000000000000)));
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the extended double-precision floating-
-| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
-| invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE commonNaNT floatx80ToCommonNaN(floatx80 a, struct float_status_t *status)
-{
- commonNaNT z;
- if (floatx80_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
- z.sign = a.exp >> 15;
- z.lo = 0;
- z.hi = a.fraction << 1;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the canonical NaN `a' to the extended
-| double-precision floating-point format.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE floatx80 commonNaNToFloatx80(commonNaNT a)
-{
- floatx80 z;
- z.fraction = BX_CONST64(0xC000000000000000) | (a.hi>>1);
- z.exp = (((Bit16u) a.sign)<<15) | 0x7FFF;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Takes two extended double-precision floating-point values `a' and `b', one
-| of which is a NaN, and returns the appropriate NaN result. If either `a' or
-| `b' is a signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Takes extended double-precision floating-point NaN `a' and returns the
-| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
-| is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE floatx80 propagateFloatx80NaNOne(floatx80 a, struct float_status_t *status)
-{
- if (floatx80_is_signaling_nan(a))
- float_raise(status, float_flag_invalid);
-
- a.fraction |= BX_CONST64(0xC000000000000000);
-
- return a;
-}
-
-#endif /* FLOATX80 */
-
-#ifdef FLOAT128
-
-#include "softfloat-macros.h"
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN. The `high' and
-| `low' values hold the most- and least-significant bits, respectively.
-*----------------------------------------------------------------------------*/
-#define float128_default_nan_hi BX_CONST64(0xFFFF800000000000)
-#define float128_default_nan_lo BX_CONST64(0x0000000000000000)
-
-#define float128_exp extractFloat128Exp
-
-/*----------------------------------------------------------------------------
-| Returns the least-significant 64 fraction bits of the quadruple-precision
-| floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit64u extractFloat128Frac1(float128 a)
-{
- return a.lo;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the most-significant 48 fraction bits of the quadruple-precision
-| floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit64u extractFloat128Frac0(float128 a)
-{
- return a.hi & BX_CONST64(0x0000FFFFFFFFFFFF);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the exponent bits of the quadruple-precision floating-point value
-| `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE Bit32s extractFloat128Exp(float128 a)
-{
- return ((Bit32s)(a.hi>>48)) & 0x7FFF;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the sign bit of the quadruple-precision floating-point value `a'.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int extractFloat128Sign(float128 a)
-{
- return (int)(a.hi >> 63);
-}
-
-/*----------------------------------------------------------------------------
-| Packs the sign `zSign', the exponent `zExp', and the significand formed
-| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
-| floating-point value, returning the result. After being shifted into the
-| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
-| added together to form the most significant 32 bits of the result. This
-| means that any integer portion of `zSig0' will be added into the exponent.
-| Since a properly normalized significand will have an integer portion equal
-| to 1, the `zExp' input should be 1 less than the desired result exponent
-| whenever `zSig0' and `zSig1' concatenated form a complete, normalized
-| significand.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float128 packFloat128Four(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1)
-{
- float128 z;
- z.lo = zSig1;
- z.hi = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Packs two 64-bit precision integers into into the quadruple-precision
-| floating-point value, returning the result.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo)
-{
- float128 z;
- z.lo = zLo;
- z.hi = zHi;
- return z;
-}
-
-#ifdef _MSC_VER
-#define PACK_FLOAT_128(hi,lo) { lo, hi }
-#else
-#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo))
-#endif
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float128_is_nan(float128 a)
-{
- return (BX_CONST64(0xFFFE000000000000) <= (Bit64u) (a.hi<<1))
- && (a.lo || (a.hi & BX_CONST64(0x0000FFFFFFFFFFFF)));
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the quadruple-precision floating-point value `a' is a
-| signaling NaN; otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float128_is_signaling_nan(float128 a)
-{
- return (((a.hi>>47) & 0xFFFF) == 0xFFFE)
- && (a.lo || (a.hi & BX_CONST64(0x00007FFFFFFFFFFF)));
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the quadruple-precision floating-point NaN
-| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
-| exception is raised.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE commonNaNT float128ToCommonNaN(float128 a, struct float_status_t *status)
-{
- commonNaNT z;
- if (float128_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
- z.sign = (int)(a.hi>>63);
- shortShift128Left(a.hi, a.lo, 16, &z.hi, &z.lo);
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the canonical NaN `a' to the quadruple-
-| precision floating-point format.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE float128 commonNaNToFloat128(commonNaNT a)
-{
- float128 z;
- shift128Right(a.hi, a.lo, 16, &z.hi, &z.lo);
- z.hi |= (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FFF800000000000);
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Takes two quadruple-precision floating-point values `a' and `b', one of
-| which is a NaN, and returns the appropriate NaN result. If either `a' or
-| `b' is a signaling NaN, the invalid exception is raised.
-*----------------------------------------------------------------------------*/
-
-float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated quadruple-precision NaN.
-*----------------------------------------------------------------------------*/
-extern const float128 float128_default_nan;
-
-#endif /* FLOAT128 */
-
-#endif
diff --git a/src/cpu/softfloat/softfloat.cc b/src/cpu/softfloat/softfloat.cc
deleted file mode 100644
index 0802089b90..0000000000
--- a/src/cpu/softfloat/softfloat.cc
+++ /dev/null
@@ -1,4012 +0,0 @@
-/*============================================================================
-This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-#define FLOAT128
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "softfloat.h"
-#include "softfloat-round-pack.h"
-
-/*----------------------------------------------------------------------------
-| Primitive arithmetic functions, including multi-word arithmetic, and
-| division and square root approximations. (Can be specialized to target
-| if desired).
-*----------------------------------------------------------------------------*/
-#define USE_estimateDiv128To64
-#define USE_estimateSqrt32
-#include "softfloat-macros.h"
-
-/*----------------------------------------------------------------------------
-| Functions and definitions to determine: (1) whether tininess for underflow
-| is detected before or after rounding by default, (2) what (if anything)
-| happens when exceptions are raised, (3) how signaling NaNs are distinguished
-| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
-| are propagated from function inputs to output. These details are target-
-| specific.
-*----------------------------------------------------------------------------*/
-#include "softfloat-specialize.h"
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the 32-bit two's complement integer `a'
-| to the single-precision floating-point format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-const unsigned float_all_exceptions_mask = 0x3f;
-
-float32 int32_to_float32(Bit32s a, struct float_status_t *status)
-{
- if (a == 0) return 0;
- if (a == (Bit32s) 0x80000000) return packFloat32(1, 0x9E, 0);
- int zSign = (a < 0);
- return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the 32-bit two's complement integer `a'
-| to the double-precision floating-point format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 int32_to_float64(Bit32s a)
-{
- if (a == 0) return 0;
- int zSign = (a < 0);
- Bit32u absA = zSign ? -a : a;
- int shiftCount = countLeadingZeros32(absA) + 21;
- Bit64u zSig = absA;
- return packFloat64(zSign, 0x432 - shiftCount, zSig<> 1, status);
- return normalizeRoundAndPackFloat32(0, 0x9C, a, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the 32-bit unsigned integer `a' to the
-| double-precision floating-point format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 uint32_to_float64(Bit32u a)
-{
- if (a == 0) return 0;
- int shiftCount = countLeadingZeros32(a) + 21;
- Bit64u zSig = a;
- return packFloat64(0, 0x432 - shiftCount, zSig<> 1, status);
- return normalizeRoundAndPackFloat64(0, 0x43C, a, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 32-bit two's complement integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic - which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the
-| conversion overflows the integer indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32s float32_to_int32(float32 a, struct float_status_t *status)
-{
- Bit32u aSig = extractFloat32Frac(a);
- Bit16s aExp = extractFloat32Exp(a);
- int aSign = extractFloat32Sign(a);
- if ((aExp == 0xFF) && aSig) aSign = 0;
- if (aExp) aSig |= 0x00800000;
- else {
- if (get_denormals_are_zeros(status)) aSig = 0;
- }
- int shiftCount = 0xAF - aExp;
- Bit64u aSig64 = Bit64u(aSig) << 32;
- if (0 < shiftCount) aSig64 = shift64RightJamming(aSig64, shiftCount);
- return roundAndPackInt32(aSign, aSig64, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 32-bit two's complement integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic, except that the conversion is always rounded toward zero.
-| If `a' is a NaN or the conversion overflows, the integer indefinite
-| value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32s float32_to_int32_round_to_zero(float32 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit32u aSig;
- Bit32s z;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- int shiftCount = aExp - 0x9E;
- if (0 <= shiftCount) {
- if (a != 0xCF000000) {
- float_raise(status, float_flag_invalid);
- }
- return (Bit32s)(int32_indefinite);
- }
- else if (aExp <= 0x7E) {
- if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0;
- if (aExp | aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
- aSig = (aSig | 0x800000)<<8;
- z = aSig>>(-shiftCount);
- if ((Bit32u) (aSig<<(shiftCount & 31))) {
- float_raise(status, float_flag_inexact);
- }
- if (aSign) z = -z;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 32-bit unsigned integer format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-point Arithmetic,
-| except that the conversion is always rounded toward zero. If `a' is a NaN
-| or conversion overflows, the largest positive integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32u float32_to_uint32_round_to_zero(float32 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit32u aSig;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- int shiftCount = aExp - 0x9E;
-
- if (aExp <= 0x7E) {
- if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0;
- if (aExp | aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
- else if (0 < shiftCount || aSign) {
- float_raise(status, float_flag_invalid);
- return uint32_indefinite;
- }
-
- aSig = (aSig | 0x800000)<<8;
- Bit32u z = aSig >> (-shiftCount);
- if (aSig << (shiftCount & 31)) {
- float_raise(status, float_flag_inexact);
- }
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 64-bit two's complement integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic - which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the
-| conversion overflows, the integer indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64s float32_to_int64(float32 a, struct float_status_t *status)
-{
- Bit64u aSig64, aSigExtra;
-
- Bit32u aSig = extractFloat32Frac(a);
- Bit16s aExp = extractFloat32Exp(a);
- int aSign = extractFloat32Sign(a);
-
- int shiftCount = 0xBE - aExp;
- if (shiftCount < 0) {
- float_raise(status, float_flag_invalid);
- return (Bit64s)(int64_indefinite);
- }
- if (aExp) aSig |= 0x00800000;
- else {
- if (get_denormals_are_zeros(status)) aSig = 0;
- }
- aSig64 = aSig;
- aSig64 <<= 40;
- shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra);
- return roundAndPackInt64(aSign, aSig64, aSigExtra, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 64-bit two's complement integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic, except that the conversion is always rounded toward zero.
-| If `a' is a NaN or the conversion overflows, the integer indefinite
-| value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64s float32_to_int64_round_to_zero(float32 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit32u aSig;
- Bit64u aSig64;
- Bit64s z;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- int shiftCount = aExp - 0xBE;
- if (0 <= shiftCount) {
- if (a != 0xDF000000) {
- float_raise(status, float_flag_invalid);
- }
- return (Bit64s)(int64_indefinite);
- }
- else if (aExp <= 0x7E) {
- if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0;
- if (aExp | aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
- aSig64 = aSig | 0x00800000;
- aSig64 <<= 40;
- z = aSig64>>(-shiftCount);
- if ((Bit64u) (aSig64<<(shiftCount & 63))) {
- float_raise(status, float_flag_inexact);
- }
- if (aSign) z = -z;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 64-bit unsigned integer format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic,
-| except that the conversion is always rounded toward zero. If `a' is a NaN
-| or the conversion overflows, the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64u float32_to_uint64_round_to_zero(float32 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit32u aSig;
- Bit64u aSig64;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- int shiftCount = aExp - 0xBE;
-
- if (aExp <= 0x7E) {
- if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0;
- if (aExp | aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
- else if (0 < shiftCount || aSign) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
-
- aSig64 = aSig | 0x00800000;
- aSig64 <<= 40;
- Bit64u z = aSig64>>(-shiftCount);
- if ((Bit64u) (aSig64<<(shiftCount & 63))) {
- float_raise(status, float_flag_inexact);
- }
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 64-bit unsigned integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic---which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the conversion
-| overflows, the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64u float32_to_uint64(float32 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp, shiftCount;
- Bit32u aSig;
- Bit64u aSig64, aSigExtra;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- }
-
- if ((aSign) && (aExp > 0x7E)) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
-
- shiftCount = 0xBE - aExp;
- if (aExp) aSig |= 0x00800000;
-
- if (shiftCount < 0) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
-
- aSig64 = aSig;
- aSig64 <<= 40;
- shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra);
- return roundAndPackUint64(aSign, aSig64, aSigExtra, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the 32-bit unsigned integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic---which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the conversion
-| overflows, the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32u float32_to_uint32(float32 a, struct float_status_t *status)
-{
- Bit64u val_64 = float32_to_uint64(a, status);
-
- if (val_64 > 0xffffffff) {
- status->float_exception_flags = float_flag_invalid; // throw away other flags
- return uint32_indefinite;
- }
-
- return (Bit32u) val_64;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the double-precision floating-point format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float32_to_float64(float32 a, struct float_status_t *status)
-{
- Bit32u aSig = extractFloat32Frac(a);
- Bit16s aExp = extractFloat32Exp(a);
- int aSign = extractFloat32Sign(a);
-
- if (aExp == 0xFF) {
- if (aSig) return commonNaNToFloat64(float32ToCommonNaN(a, status));
- return packFloat64(aSign, 0x7FF, 0);
- }
- if (aExp == 0) {
- if (aSig == 0 || get_denormals_are_zeros(status))
- return packFloat64(aSign, 0, 0);
-
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
- --aExp;
- }
- return packFloat64(aSign, aExp + 0x380, ((Bit64u) aSig)<<29);
-}
-
-/*----------------------------------------------------------------------------
-| Rounds the single-precision floating-point value `a' to an integer, and
-| returns the result as a single-precision floating-point value. The
-| operation is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_round_to_int(float32 a, Bit8u scale, struct float_status_t *status)
-{
- Bit32u lastBitMask, roundBitsMask;
- int roundingMode = get_float_rounding_mode(status);
- Bit16s aExp = extractFloat32Exp(a);
- scale &= 0xf;
-
- if ((aExp == 0xFF) && extractFloat32Frac(a)) {
- return propagateFloat32NaNOne(a, status);
- }
-
- aExp += scale; // scale the exponent
-
- if (0x96 <= aExp) {
- return a;
- }
-
- if (get_denormals_are_zeros(status)) {
- a = float32_denormal_to_zero(a);
- }
-
- if (aExp <= 0x7E) {
- if ((Bit32u) (a<<1) == 0) return a;
- float_raise(status, float_flag_inexact);
- int aSign = extractFloat32Sign(a);
- switch (roundingMode) {
- case float_round_nearest_even:
- if ((aExp == 0x7E) && extractFloat32Frac(a)) {
- return packFloat32(aSign, 0x7F - scale, 0);
- }
- break;
- case float_round_down:
- return aSign ? packFloat32(1, 0x7F - scale, 0) : float32_positive_zero;
- case float_round_up:
- return aSign ? float32_negative_zero : packFloat32(0, 0x7F - scale, 0);
- }
- return packFloat32(aSign, 0, 0);
- }
-
- lastBitMask = 1;
- lastBitMask <<= 0x96 - aExp;
- roundBitsMask = lastBitMask - 1;
- float32 z = a;
- if (roundingMode == float_round_nearest_even) {
- z += lastBitMask>>1;
- if ((z & roundBitsMask) == 0) z &= ~lastBitMask;
- }
- else if (roundingMode != float_round_to_zero) {
- if (extractFloat32Sign(z) ^ (roundingMode == float_round_up)) {
- z += roundBitsMask;
- }
- }
- z &= ~roundBitsMask;
- if (z != a) float_raise(status, float_flag_inexact);
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Extracts the fractional portion of single-precision floating-point value `a',
-| and returns the result as a single-precision floating-point value. The
-| fractional results are precise. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_frc(float32 a, struct float_status_t *status)
-{
- int roundingMode = get_float_rounding_mode(status);
-
- Bit16s aExp = extractFloat32Exp(a);
- Bit32u aSig = extractFloat32Frac(a);
- int aSign = extractFloat32Sign(a);
-
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaNOne(a, status);
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
-
- if (aExp >= 0x96) {
- return packFloat32(roundingMode == float_round_down, 0, 0);
- }
-
- if (aExp < 0x7F) {
- if (aExp == 0) {
- if (aSig == 0 || get_denormals_are_zeros(status))
- return packFloat32(roundingMode == float_round_down, 0, 0);
-
- float_raise(status, float_flag_denormal);
- if (! float_exception_masked(status, float_flag_underflow))
- float_raise(status, float_flag_underflow);
-
- if(get_flush_underflow_to_zero(status)) {
- float_raise(status, float_flag_underflow | float_flag_inexact);
- return packFloat32(aSign, 0, 0);
- }
- }
- return a;
- }
-
- Bit32u lastBitMask = 1 << (0x96 - aExp);
- Bit32u roundBitsMask = lastBitMask - 1;
-
- aSig &= roundBitsMask;
- aSig <<= 7;
- aExp--;
-
- if (aSig == 0)
- return packFloat32(roundingMode == float_round_down, 0, 0);
-
- return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Extracts the exponent portion of single-precision floating-point value 'a',
-| and returns the result as a single-precision floating-point value
-| representing unbiased integer exponent. The operation is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_getexp(float32 a, struct float_status_t *status)
-{
- Bit16s aExp = extractFloat32Exp(a);
- Bit32u aSig = extractFloat32Frac(a);
-
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaNOne(a, status);
- return float32_positive_inf;
- }
-
- if (aExp == 0) {
- if (aSig == 0 || get_denormals_are_zeros(status))
- return float32_negative_inf;
-
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
- }
-
- return int32_to_float32(aExp - 0x7F, status);
-}
-
-/*----------------------------------------------------------------------------
-| Extracts the mantissa of single-precision floating-point value 'a' and
-| returns the result as a single-precision floating-point after applying
-| the mantissa interval normalization and sign control. The operation is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv)
-{
- Bit16s aExp = extractFloat32Exp(a);
- Bit32u aSig = extractFloat32Frac(a);
- int aSign = extractFloat32Sign(a);
-
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaNOne(a, status);
- if (aSign) {
- if (sign_ctrl & 0x2) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- }
- return packFloat32(~sign_ctrl & aSign, 0x7F, 0);
- }
-
- if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) {
- return packFloat32(~sign_ctrl & aSign, 0x7F, 0);
- }
-
- if (aSign) {
- if (sign_ctrl & 0x2) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- }
-
- if (aExp == 0) {
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
-// aExp += 0x7E;
- aSig &= 0x7FFFFF;
- }
-
- switch(interv) {
- case 0x0: // interval [1,2)
- aExp = 0x7F;
- break;
- case 0x1: // interval [1/2,2)
- aExp -= 0x7F;
- aExp = 0x7F - (aExp & 0x1);
- break;
- case 0x2: // interval [1/2,1)
- aExp = 0x7E;
- break;
- case 0x3: // interval [3/4,3/2)
- aExp = 0x7F - ((aSig >> 22) & 0x1);
- break;
- }
-
- return packFloat32(~sign_ctrl & aSign, aExp, aSig);
-}
-
-/*----------------------------------------------------------------------------
-| Return the result of a floating point scale of the single-precision floating
-| point value `a' by multiplying it by 2 power of the single-precision
-| floating point value 'b' converted to integral value. If the result cannot
-| be represented in single precision, then the proper overflow response (for
-| positive scaling operand), or the proper underflow response (for negative
-| scaling operand) is issued. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_scalef(float32 a, float32 b, struct float_status_t *status)
-{
- Bit32u aSig = extractFloat32Frac(a);
- Bit16s aExp = extractFloat32Exp(a);
- int aSign = extractFloat32Sign(a);
- Bit32u bSig = extractFloat32Frac(b);
- Bit16s bExp = extractFloat32Exp(b);
- int bSign = extractFloat32Sign(b);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- if (bExp == 0xFF) {
- if (bSig) return propagateFloat32NaN(a, b, status);
- }
-
- if (aExp == 0xFF) {
- if (aSig) {
- int aIsSignalingNaN = (aSig & 0x00400000) == 0;
- if (aIsSignalingNaN || bExp != 0xFF || bSig)
- return propagateFloat32NaN(a, b, status);
-
- return bSign ? 0 : float32_positive_inf;
- }
-
- if (bExp == 0xFF && bSign) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- return a;
- }
-
- if (aExp == 0) {
- if (aSig == 0) {
- if (bExp == 0xFF && ! bSign) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- return a;
- }
- float_raise(status, float_flag_denormal);
- }
-
- if ((bExp | bSig) == 0) return a;
-
- if (bExp == 0xFF) {
- if (bSign) return packFloat32(aSign, 0, 0);
- return packFloat32(aSign, 0xFF, 0);
- }
-
- if (bExp >= 0x8E) {
- // handle obvious overflow/underflow result
- return roundAndPackFloat32(aSign, bSign ? -0x7F : 0xFF, aSig, status);
- }
-
- int scale = 0;
-
- if (bExp <= 0x7E) {
- if (bExp == 0)
- float_raise(status, float_flag_denormal);
- scale = -bSign;
- }
- else {
- int shiftCount = bExp - 0x9E;
- bSig = (bSig | 0x800000)<<8;
- scale = bSig>>(-shiftCount);
-
- if (bSign) {
- if ((Bit32u) (bSig<<(shiftCount & 31))) scale++;
- scale = -scale;
- }
-
- if (scale > 0x200) scale = 0x200;
- if (scale < -0x200) scale = -0x200;
- }
-
- if (aExp != 0) {
- aSig |= 0x00800000;
- } else {
- aExp++;
- }
-
- aExp += scale - 1;
- aSig <<= 7;
- return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the absolute values of the single-precision
-| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
-| before being returned. `zSign' is ignored if the result is a NaN.
-| The addition is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static float32 addFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status)
-{
- Bit16s aExp, bExp, zExp;
- Bit32u aSig, bSig, zSig;
- Bit16s expDiff;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- bSig = extractFloat32Frac(b);
- bExp = extractFloat32Exp(b);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- expDiff = aExp - bExp;
- aSig <<= 6;
- bSig <<= 6;
-
- if (0 < expDiff) {
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaN(a, b, status);
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if ((aExp == 0) && aSig)
- float_raise(status, float_flag_denormal);
-
- if (bExp == 0) {
- if (bSig) float_raise(status, float_flag_denormal);
- --expDiff;
- }
- else bSig |= 0x20000000;
-
- bSig = shift32RightJamming(bSig, expDiff);
- zExp = aExp;
- }
- else if (expDiff < 0) {
- if (bExp == 0xFF) {
- if (bSig) return propagateFloat32NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign, 0xFF, 0);
- }
- if ((bExp == 0) && bSig)
- float_raise(status, float_flag_denormal);
-
- if (aExp == 0) {
- if (aSig) float_raise(status, float_flag_denormal);
- ++expDiff;
- }
- else aSig |= 0x20000000;
-
- aSig = shift32RightJamming(aSig, -expDiff);
- zExp = bExp;
- }
- else {
- if (aExp == 0xFF) {
- if (aSig | bSig) return propagateFloat32NaN(a, b, status);
- return a;
- }
- if (aExp == 0) {
- zSig = (aSig + bSig) >> 6;
- if (aSig | bSig) {
- float_raise(status, float_flag_denormal);
- if (get_flush_underflow_to_zero(status) && (extractFloat32Frac(zSig) == zSig)) {
- float_raise(status, float_flag_underflow | float_flag_inexact);
- return packFloat32(zSign, 0, 0);
- }
- if (! float_exception_masked(status, float_flag_underflow)) {
- if (extractFloat32Frac(zSig) == zSig)
- float_raise(status, float_flag_underflow);
- }
- }
- return packFloat32(zSign, 0, zSig);
- }
- zSig = 0x40000000 + aSig + bSig;
- return roundAndPackFloat32(zSign, aExp, zSig, status);
- }
- aSig |= 0x20000000;
- zSig = (aSig + bSig)<<1;
- --zExp;
- if ((Bit32s) zSig < 0) {
- zSig = aSig + bSig;
- ++zExp;
- }
- return roundAndPackFloat32(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the absolute values of the single-
-| precision floating-point values `a' and `b'. If `zSign' is 1, the
-| difference is negated before being returned. `zSign' is ignored if the
-| result is a NaN. The subtraction is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static float32 subFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status)
-{
- Bit16s aExp, bExp, zExp;
- Bit32u aSig, bSig, zSig;
- Bit16s expDiff;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- bSig = extractFloat32Frac(b);
- bExp = extractFloat32Exp(b);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- expDiff = aExp - bExp;
- aSig <<= 7;
- bSig <<= 7;
- if (0 < expDiff) goto aExpBigger;
- if (expDiff < 0) goto bExpBigger;
- if (aExp == 0xFF) {
- if (aSig | bSig) return propagateFloat32NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- if (aExp == 0) {
- if (aSig | bSig) float_raise(status, float_flag_denormal);
- aExp = 1;
- bExp = 1;
- }
- if (bSig < aSig) goto aBigger;
- if (aSig < bSig) goto bBigger;
- return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0);
- bExpBigger:
- if (bExp == 0xFF) {
- if (bSig) return propagateFloat32NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign ^ 1, 0xFF, 0);
- }
- if ((bExp == 0) && bSig)
- float_raise(status, float_flag_denormal);
-
- if (aExp == 0) {
- if (aSig) float_raise(status, float_flag_denormal);
- ++expDiff;
- }
- else aSig |= 0x40000000;
-
- aSig = shift32RightJamming(aSig, -expDiff);
- bSig |= 0x40000000;
- bBigger:
- zSig = bSig - aSig;
- zExp = bExp;
- zSign ^= 1;
- goto normalizeRoundAndPack;
- aExpBigger:
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaN(a, b, status);
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if ((aExp == 0) && aSig)
- float_raise(status, float_flag_denormal);
-
- if (bExp == 0) {
- if (bSig) float_raise(status, float_flag_denormal);
- --expDiff;
- }
- else bSig |= 0x40000000;
-
- bSig = shift32RightJamming(bSig, expDiff);
- aSig |= 0x40000000;
- aBigger:
- zSig = aSig - bSig;
- zExp = aExp;
- normalizeRoundAndPack:
- --zExp;
- return normalizeRoundAndPackFloat32(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the single-precision floating-point values `a'
-| and `b'. The operation is performed according to the IEC/IEEE Standard for
-| Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_add(float32 a, float32 b, struct float_status_t *status)
-{
- int aSign = extractFloat32Sign(a);
- int bSign = extractFloat32Sign(b);
-
- if (aSign == bSign) {
- return addFloat32Sigs(a, b, aSign, status);
- }
- else {
- return subFloat32Sigs(a, b, aSign, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the single-precision floating-point values
-| `a' and `b'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_sub(float32 a, float32 b, struct float_status_t *status)
-{
- int aSign = extractFloat32Sign(a);
- int bSign = extractFloat32Sign(b);
-
- if (aSign == bSign) {
- return subFloat32Sigs(a, b, aSign, status);
- }
- else {
- return addFloat32Sigs(a, b, aSign, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the single-precision floating-point values
-| `a' and `b'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_mul(float32 a, float32 b, struct float_status_t *status)
-{
- int aSign, bSign, zSign;
- Bit16s aExp, bExp, zExp;
- Bit32u aSig, bSig;
- Bit64u zSig64;
- Bit32u zSig;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- bSig = extractFloat32Frac(b);
- bExp = extractFloat32Exp(b);
- bSign = extractFloat32Sign(b);
- zSign = aSign ^ bSign;
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- if (aExp == 0xFF) {
- if (aSig || ((bExp == 0xFF) && bSig))
- return propagateFloat32NaN(a, b, status);
-
- if ((bExp | bSig) == 0) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign, 0xFF, 0);
- }
- if (bExp == 0xFF) {
- if (bSig) return propagateFloat32NaN(a, b, status);
- if ((aExp | aSig) == 0) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign, 0xFF, 0);
- }
- if (aExp == 0) {
- if (aSig == 0) {
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign, 0, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- if (bSig == 0) return packFloat32(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(bSig, &bExp, &bSig);
- }
- zExp = aExp + bExp - 0x7F;
- aSig = (aSig | 0x00800000)<<7;
- bSig = (bSig | 0x00800000)<<8;
- zSig64 = shift64RightJamming(((Bit64u) aSig) * bSig, 32);
- zSig = (Bit32u) zSig64;
- if (0 <= (Bit32s) (zSig<<1)) {
- zSig <<= 1;
- --zExp;
- }
- return roundAndPackFloat32(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of dividing the single-precision floating-point value `a'
-| by the corresponding value `b'. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_div(float32 a, float32 b, struct float_status_t *status)
-{
- int aSign, bSign, zSign;
- Bit16s aExp, bExp, zExp;
- Bit32u aSig, bSig, zSig;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
- bSig = extractFloat32Frac(b);
- bExp = extractFloat32Exp(b);
- bSign = extractFloat32Sign(b);
- zSign = aSign ^ bSign;
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaN(a, b, status);
- if (bExp == 0xFF) {
- if (bSig) return propagateFloat32NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign, 0xFF, 0);
- }
- if (bExp == 0xFF) {
- if (bSig) return propagateFloat32NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat32(zSign, 0, 0);
- }
- if (bExp == 0) {
- if (bSig == 0) {
- if ((aExp | aSig) == 0) {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- float_raise(status, float_flag_divbyzero);
- return packFloat32(zSign, 0xFF, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(bSig, &bExp, &bSig);
- }
- if (aExp == 0) {
- if (aSig == 0) return packFloat32(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
- }
- zExp = aExp - bExp + 0x7D;
- aSig = (aSig | 0x00800000)<<7;
- bSig = (bSig | 0x00800000)<<8;
- if (bSig <= (aSig + aSig)) {
- aSig >>= 1;
- ++zExp;
- }
- zSig = (((Bit64u) aSig)<<32) / bSig;
- if ((zSig & 0x3F) == 0) {
- zSig |= ((Bit64u) bSig * zSig != ((Bit64u) aSig)<<32);
- }
- return roundAndPackFloat32(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the square root of the single-precision floating-point value `a'.
-| The operation is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_sqrt(float32 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp, zExp;
- Bit32u aSig, zSig;
- Bit64u rem, term;
-
- aSig = extractFloat32Frac(a);
- aExp = extractFloat32Exp(a);
- aSign = extractFloat32Sign(a);
-
- if (aExp == 0xFF) {
- if (aSig) return propagateFloat32NaNOne(a, status);
- if (! aSign) return a;
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- }
-
- if (aSign) {
- if ((aExp | aSig) == 0) return packFloat32(aSign, 0, 0);
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
- if (aExp == 0) {
- if (aSig == 0) return 0;
- float_raise(status, float_flag_denormal);
- normalizeFloat32Subnormal(aSig, &aExp, &aSig);
- }
- zExp = ((aExp - 0x7F)>>1) + 0x7E;
- aSig = (aSig | 0x00800000)<<8;
- zSig = estimateSqrt32(aExp, aSig) + 2;
- if ((zSig & 0x7F) <= 5) {
- if (zSig < 2) {
- zSig = 0x7FFFFFFF;
- goto roundAndPack;
- }
- aSig >>= aExp & 1;
- term = ((Bit64u) zSig) * zSig;
- rem = (((Bit64u) aSig)<<32) - term;
- while ((Bit64s) rem < 0) {
- --zSig;
- rem += (((Bit64u) zSig)<<1) | 1;
- }
- zSig |= (rem != 0);
- }
- zSig = shift32RightJamming(zSig, 1);
- roundAndPack:
- return roundAndPackFloat32(0, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Determine single-precision floating-point number class.
-*----------------------------------------------------------------------------*/
-
-float_class_t float32_class(float32 a)
-{
- Bit16s aExp = extractFloat32Exp(a);
- Bit32u aSig = extractFloat32Frac(a);
- int aSign = extractFloat32Sign(a);
-
- if(aExp == 0xFF) {
- if (aSig == 0)
- return (aSign) ? float_negative_inf : float_positive_inf;
-
- return (aSig & 0x00400000) ? float_QNaN : float_SNaN;
- }
-
- if(aExp == 0) {
- if (aSig == 0) return float_zero;
- return float_denormal;
- }
-
- return float_normalized;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two single precision floating point numbers. Returns
-| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
-| the value 'a' is less than the corresponding value `b',
-| 'float_relation_greater' if the value 'a' is greater than the corresponding
-| value `b', or 'float_relation_unordered' otherwise.
-*----------------------------------------------------------------------------*/
-
-int float32_compare(float32 a, float32 b, int quiet, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float32_denormal_to_zero(a);
- b = float32_denormal_to_zero(b);
- }
-
- float_class_t aClass = float32_class(a);
- float_class_t bClass = float32_class(b);
-
- if (aClass == float_SNaN || bClass == float_SNaN) {
- float_raise(status, float_flag_invalid);
- return float_relation_unordered;
- }
-
- if (aClass == float_QNaN || bClass == float_QNaN) {
- if (! quiet) float_raise(status, float_flag_invalid);
- return float_relation_unordered;
- }
-
- if (aClass == float_denormal || bClass == float_denormal) {
- float_raise(status, float_flag_denormal);
- }
-
- if ((a == b) || ((Bit32u) ((a | b)<<1) == 0)) return float_relation_equal;
-
- int aSign = extractFloat32Sign(a);
- int bSign = extractFloat32Sign(b);
- if (aSign != bSign)
- return (aSign) ? float_relation_less : float_relation_greater;
-
- if (aSign ^ (a < b)) return float_relation_less;
- return float_relation_greater;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two single precision floating point numbers and return the
-| smaller of them.
-*----------------------------------------------------------------------------*/
-
-float32 float32_min(float32 a, float32 b, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float32_denormal_to_zero(a);
- b = float32_denormal_to_zero(b);
- }
-
- return (float32_compare_two(a, b, status) == float_relation_less) ? a : b;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two single precision floating point numbers and return the
-| larger of them.
-*----------------------------------------------------------------------------*/
-
-float32 float32_max(float32 a, float32 b, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float32_denormal_to_zero(a);
- b = float32_denormal_to_zero(b);
- }
-
- return (float32_compare_two(a, b, status) == float_relation_greater) ? a : b;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two single precision floating point numbers and return the
-| smaller/larger of them. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float32_denormal_to_zero(a);
- b = float32_denormal_to_zero(b);
- }
-
- if (float32_is_nan(a) || float32_is_nan(b)) {
- if (float32_is_signaling_nan(a)) {
- return propagateFloat32NaNOne(a, status);
- }
- if (float32_is_signaling_nan(b) ) {
- return propagateFloat32NaNOne(b, status);
- }
- if (! float32_is_nan(b)) {
- if (float32_is_denormal(b))
- float_raise(status, float_flag_denormal);
- return b;
- }
- if (! float32_is_nan(a)) {
- if (float32_is_denormal(a))
- float_raise(status, float_flag_denormal);
- return a;
- }
- return propagateFloat32NaN(a, b, status);
- }
-
- float32 tmp_a = a, tmp_b = b;
- if (is_abs) {
- tmp_a &= ~0x80000000; // clear the sign bit
- tmp_b &= ~0x80000000;
- }
-
- int aSign = extractFloat32Sign(tmp_a);
- int bSign = extractFloat32Sign(tmp_b);
-
- if (float32_is_denormal(a) || float32_is_denormal(b))
- float_raise(status, float_flag_denormal);
-
- if (aSign != bSign) {
- if (! is_max) {
- return aSign ? a : b;
- } else {
- return aSign ? b : a;
- }
- } else {
- if (! is_max) {
- return (aSign ^ (tmp_a < tmp_b)) ? a : b;
- } else {
- return (aSign ^ (tmp_a < tmp_b)) ? b : a;
- }
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point value
-| `a' to the 32-bit two's complement integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic - which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the
-| conversion overflows, the integer indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32s float64_to_int32(float64 a, struct float_status_t *status)
-{
- Bit64u aSig = extractFloat64Frac(a);
- Bit16s aExp = extractFloat64Exp(a);
- int aSign = extractFloat64Sign(a);
- if ((aExp == 0x7FF) && aSig) aSign = 0;
- if (aExp) aSig |= BX_CONST64(0x0010000000000000);
- else {
- if (get_denormals_are_zeros(status)) aSig = 0;
- }
- int shiftCount = 0x42C - aExp;
- if (0 < shiftCount) aSig = shift64RightJamming(aSig, shiftCount);
- return roundAndPackInt32(aSign, aSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point value
-| `a' to the 32-bit two's complement integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic, except that the conversion is always rounded toward zero.
-| If `a' is a NaN or the conversion overflows, the integer indefinite
-| value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32s float64_to_int32_round_to_zero(float64 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit64u aSig, savedASig;
- Bit32s z;
- int shiftCount;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
- if (0x41E < aExp) {
- float_raise(status, float_flag_invalid);
- return (Bit32s)(int32_indefinite);
- }
- else if (aExp < 0x3FF) {
- if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0;
- if (aExp || aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
- aSig |= BX_CONST64(0x0010000000000000);
- shiftCount = 0x433 - aExp;
- savedASig = aSig;
- aSig >>= shiftCount;
- z = (Bit32s) aSig;
- if (aSign) z = -z;
- if ((z < 0) ^ aSign) {
- float_raise(status, float_flag_invalid);
- return (Bit32s)(int32_indefinite);
- }
- if ((aSig<>= shiftCount;
- if ((aSig<>(-shiftCount);
- if ((Bit64u) (aSig<<(shiftCount & 63))) {
- float_raise(status, float_flag_inexact);
- }
- }
- if (aSign) z = -z;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point value
-| `a' to the 64-bit unsigned integer format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic,
-| except that the conversion is always rounded toward zero. If `a' is a NaN
-| or the conversion overflows, the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64u float64_to_uint64_round_to_zero(float64 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit64u aSig, z;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
-
- if (aExp < 0x3FE) {
- if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0;
- if (aExp | aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
-
- if (0x43E <= aExp || aSign) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
-
- if (aExp) aSig |= BX_CONST64(0x0010000000000000);
- int shiftCount = aExp - 0x433;
-
- if (0 <= shiftCount) {
- z = aSig<>(-shiftCount);
- if ((Bit64u) (aSig<<(shiftCount & 63))) {
- float_raise(status, float_flag_inexact);
- }
- }
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point value
-| `a' to the 32-bit unsigned integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic---which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the conversion
-| overflows, the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit32u float64_to_uint32(float64 a, struct float_status_t *status)
-{
- Bit64u val_64 = float64_to_uint64(a, status);
-
- if (val_64 > 0xffffffff) {
- status->float_exception_flags = float_flag_invalid; // throw away other flags
- return uint32_indefinite;
- }
-
- return (Bit32u) val_64;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point value
-| `a' to the 64-bit unsigned integer format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic---which means in particular that the conversion is rounded
-| according to the current rounding mode. If `a' is a NaN or the conversion
-| overflows, the largest unsigned integer is returned.
-*----------------------------------------------------------------------------*/
-
-Bit64u float64_to_uint64(float64 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp, shiftCount;
- Bit64u aSig, aSigExtra;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- }
-
- if (aSign && (aExp > 0x3FE)) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
-
- if (aExp) {
- aSig |= BX_CONST64(0x0010000000000000);
- }
- shiftCount = 0x433 - aExp;
- if (shiftCount <= 0) {
- if (0x43E < aExp) {
- float_raise(status, float_flag_invalid);
- return uint64_indefinite;
- }
- aSigExtra = 0;
- aSig <<= -shiftCount;
- } else {
- shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra);
- }
-
- return roundAndPackUint64(aSign, aSig, aSigExtra, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the double-precision floating-point value
-| `a' to the single-precision floating-point format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float64_to_float32(float64 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp;
- Bit64u aSig;
- Bit32u zSig;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
- if (aExp == 0x7FF) {
- if (aSig) return commonNaNToFloat32(float64ToCommonNaN(a, status));
- return packFloat32(aSign, 0xFF, 0);
- }
- if (aExp == 0) {
- if (aSig == 0 || get_denormals_are_zeros(status))
- return packFloat32(aSign, 0, 0);
- float_raise(status, float_flag_denormal);
- }
- aSig = shift64RightJamming(aSig, 22);
- zSig = (Bit32u) aSig;
- if (aExp || zSig) {
- zSig |= 0x40000000;
- aExp -= 0x381;
- }
- return roundAndPackFloat32(aSign, aExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Rounds the double-precision floating-point value `a' to an integer, and
-| returns the result as a double-precision floating-point value. The
-| operation is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_round_to_int(float64 a, Bit8u scale, struct float_status_t *status)
-{
- Bit64u lastBitMask, roundBitsMask;
- int roundingMode = get_float_rounding_mode(status);
- Bit16s aExp = extractFloat64Exp(a);
- scale &= 0xf;
-
- if ((aExp == 0x7FF) && extractFloat64Frac(a)) {
- return propagateFloat64NaNOne(a, status);
- }
-
- aExp += scale; // scale the exponent
-
- if (0x433 <= aExp) {
- return a;
- }
-
- if (get_denormals_are_zeros(status)) {
- a = float64_denormal_to_zero(a);
- }
-
- if (aExp < 0x3FF) {
- if ((Bit64u) (a<<1) == 0) return a;
- float_raise(status, float_flag_inexact);
- int aSign = extractFloat64Sign(a);
- switch (roundingMode) {
- case float_round_nearest_even:
- if ((aExp == 0x3FE) && extractFloat64Frac(a)) {
- return packFloat64(aSign, 0x3FF - scale, 0);
- }
- break;
- case float_round_down:
- return aSign ? packFloat64(1, 0x3FF - scale, 0) : float64_positive_zero;
- case float_round_up:
- return aSign ? float64_negative_zero : packFloat64(0, 0x3FF - scale, 0);
- }
- return packFloat64(aSign, 0, 0);
- }
-
- lastBitMask = 1;
- lastBitMask <<= 0x433 - aExp;
- roundBitsMask = lastBitMask - 1;
- float64 z = a;
- if (roundingMode == float_round_nearest_even) {
- z += lastBitMask>>1;
- if ((z & roundBitsMask) == 0) z &= ~lastBitMask;
- }
- else if (roundingMode != float_round_to_zero) {
- if (extractFloat64Sign(z) ^ (roundingMode == float_round_up)) {
- z += roundBitsMask;
- }
- }
- z &= ~roundBitsMask;
- if (z != a) float_raise(status, float_flag_inexact);
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Extracts the fractional portion of double-precision floating-point value `a',
-| and returns the result as a double-precision floating-point value. The
-| fractional results are precise. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_frc(float64 a, struct float_status_t *status)
-{
- int roundingMode = get_float_rounding_mode(status);
-
- Bit64u aSig = extractFloat64Frac(a);
- Bit16s aExp = extractFloat64Exp(a);
- int aSign = extractFloat64Sign(a);
-
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaNOne(a, status);
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
-
- if (aExp >= 0x433) {
- return packFloat64(roundingMode == float_round_down, 0, 0);
- }
-
- if (aExp < 0x3FF) {
- if (aExp == 0) {
- if (aSig == 0 || get_denormals_are_zeros(status))
- return packFloat64(roundingMode == float_round_down, 0, 0);
-
- float_raise(status, float_flag_denormal);
- if (! float_exception_masked(status, float_flag_underflow))
- float_raise(status, float_flag_underflow);
-
- if(get_flush_underflow_to_zero(status)) {
- float_raise(status, float_flag_underflow | float_flag_inexact);
- return packFloat64(aSign, 0, 0);
- }
- }
- return a;
- }
-
- Bit64u lastBitMask = BX_CONST64(1) << (0x433 - aExp);
- Bit64u roundBitsMask = lastBitMask - 1;
-
- aSig &= roundBitsMask;
- aSig <<= 10;
- aExp--;
-
- if (aSig == 0)
- return packFloat64(roundingMode == float_round_down, 0, 0);
-
- return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Extracts the exponent portion of double-precision floating-point value 'a',
-| and returns the result as a double-precision floating-point value
-| representing unbiased integer exponent. The operation is performed according
-| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_getexp(float64 a, struct float_status_t *status)
-{
- Bit16s aExp = extractFloat64Exp(a);
- Bit64u aSig = extractFloat64Frac(a);
-
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaNOne(a, status);
- return float64_positive_inf;
- }
-
- if (aExp == 0) {
- if (aSig == 0 || get_denormals_are_zeros(status))
- return float64_negative_inf;
-
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(aSig, &aExp, &aSig);
- }
-
- return int32_to_float64(aExp - 0x3FF);
-}
-
-/*----------------------------------------------------------------------------
-| Extracts the mantissa of double-precision floating-point value 'a' and
-| returns the result as a double-precision floating-point after applying
-| the mantissa interval normalization and sign control. The operation is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv)
-{
- Bit16s aExp = extractFloat64Exp(a);
- Bit64u aSig = extractFloat64Frac(a);
- int aSign = extractFloat64Sign(a);
-
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaNOne(a, status);
- if (aSign) {
- if (sign_ctrl & 0x2) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- }
- return packFloat64(~sign_ctrl & aSign, 0x3FF, 0);
- }
-
- if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) {
- return packFloat64(~sign_ctrl & aSign, 0x3FF, 0);
- }
-
- if (aSign) {
- if (sign_ctrl & 0x2) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- }
-
- if (aExp == 0) {
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(aSig, &aExp, &aSig);
-// aExp += 0x3FE;
- aSig &= BX_CONST64(0xFFFFFFFFFFFFFFFF);
- }
-
- switch(interv) {
- case 0x0: // interval [1,2)
- aExp = 0x3FF;
- break;
- case 0x1: // interval [1/2,2)
- aExp -= 0x3FF;
- aExp = 0x3FF - (aExp & 0x1);
- break;
- case 0x2: // interval [1/2,1)
- aExp = 0x3FE;
- break;
- case 0x3: // interval [3/4,3/2)
- aExp = 0x3FF - ((aSig >> 51) & 0x1);
- break;
- }
-
- return packFloat64(~sign_ctrl & aSign, aExp, aSig);
-}
-
-/*----------------------------------------------------------------------------
-| Return the result of a floating point scale of the double-precision floating
-| point value `a' by multiplying it by 2 power of the double-precision
-| floating point value 'b' converted to integral value. If the result cannot
-| be represented in double precision, then the proper overflow response (for
-| positive scaling operand), or the proper underflow response (for negative
-| scaling operand) is issued. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_scalef(float64 a, float64 b, struct float_status_t *status)
-{
- Bit64u aSig = extractFloat64Frac(a);
- Bit16s aExp = extractFloat64Exp(a);
- int aSign = extractFloat64Sign(a);
- Bit64u bSig = extractFloat64Frac(b);
- Bit16s bExp = extractFloat64Exp(b);
- int bSign = extractFloat64Sign(b);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- if (bExp == 0x7FF) {
- if (bSig) return propagateFloat64NaN(a, b, status);
- }
-
- if (aExp == 0x7FF) {
- if (aSig) {
- int aIsSignalingNaN = (aSig & BX_CONST64(0x0008000000000000)) == 0;
- if (aIsSignalingNaN || bExp != 0x7FF || bSig)
- return propagateFloat64NaN(a, b, status);
-
- return bSign ? 0 : float64_positive_inf;
- }
-
- if (bExp == 0x7FF && bSign) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- return a;
- }
-
- if (aExp == 0) {
- if (aSig == 0) {
- if (bExp == 0x7FF && ! bSign) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- return a;
- }
- float_raise(status, float_flag_denormal);
- }
-
- if ((bExp | bSig) == 0) return a;
-
- if (bExp == 0x7FF) {
- if (bSign) return packFloat64(aSign, 0, 0);
- return packFloat64(aSign, 0x7FF, 0);
- }
-
- if (0x40F <= bExp) {
- // handle obvious overflow/underflow result
- return roundAndPackFloat64(aSign, bSign ? -0x3FF : 0x7FF, aSig, status);
- }
-
- int scale = 0;
-
- if (bExp < 0x3FF) {
- if (bExp == 0)
- float_raise(status, float_flag_denormal);
- scale = -bSign;
- }
- else {
- bSig |= BX_CONST64(0x0010000000000000);
- int shiftCount = 0x433 - bExp;
- Bit64u savedBSig = bSig;
- bSig >>= shiftCount;
- scale = (Bit32s) bSig;
- if (bSign) {
- if ((bSig< 0x1000) scale = 0x1000;
- if (scale < -0x1000) scale = -0x1000;
- }
-
- if (aExp != 0) {
- aSig |= BX_CONST64(0x0010000000000000);
- } else {
- aExp++;
- }
-
- aExp += scale - 1;
- aSig <<= 10;
- return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the absolute values of the double-precision
-| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
-| before being returned. `zSign' is ignored if the result is a NaN.
-| The addition is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static float64 addFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status)
-{
- Bit16s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig;
- Bit16s expDiff;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- bSig = extractFloat64Frac(b);
- bExp = extractFloat64Exp(b);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- expDiff = aExp - bExp;
- aSig <<= 9;
- bSig <<= 9;
- if (0 < expDiff) {
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaN(a, b, status);
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if ((aExp == 0) && aSig)
- float_raise(status, float_flag_denormal);
-
- if (bExp == 0) {
- if (bSig) float_raise(status, float_flag_denormal);
- --expDiff;
- }
- else bSig |= BX_CONST64(0x2000000000000000);
-
- bSig = shift64RightJamming(bSig, expDiff);
- zExp = aExp;
- }
- else if (expDiff < 0) {
- if (bExp == 0x7FF) {
- if (bSig) return propagateFloat64NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign, 0x7FF, 0);
- }
- if ((bExp == 0) && bSig)
- float_raise(status, float_flag_denormal);
-
- if (aExp == 0) {
- if (aSig) float_raise(status, float_flag_denormal);
- ++expDiff;
- }
- else aSig |= BX_CONST64(0x2000000000000000);
-
- aSig = shift64RightJamming(aSig, -expDiff);
- zExp = bExp;
- }
- else {
- if (aExp == 0x7FF) {
- if (aSig | bSig) return propagateFloat64NaN(a, b, status);
- return a;
- }
- if (aExp == 0) {
- zSig = (aSig + bSig) >> 9;
- if (aSig | bSig) {
- float_raise(status, float_flag_denormal);
- if (get_flush_underflow_to_zero(status) && (extractFloat64Frac(zSig) == zSig)) {
- float_raise(status, float_flag_underflow | float_flag_inexact);
- return packFloat64(zSign, 0, 0);
- }
- if (! float_exception_masked(status, float_flag_underflow)) {
- if (extractFloat64Frac(zSig) == zSig)
- float_raise(status, float_flag_underflow);
- }
- }
- return packFloat64(zSign, 0, zSig);
- }
- zSig = BX_CONST64(0x4000000000000000) + aSig + bSig;
- return roundAndPackFloat64(zSign, aExp, zSig, status);
- }
- aSig |= BX_CONST64(0x2000000000000000);
- zSig = (aSig + bSig)<<1;
- --zExp;
- if ((Bit64s) zSig < 0) {
- zSig = aSig + bSig;
- ++zExp;
- }
- return roundAndPackFloat64(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the absolute values of the double-
-| precision floating-point values `a' and `b'. If `zSign' is 1, the
-| difference is negated before being returned. `zSign' is ignored if the
-| result is a NaN. The subtraction is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static float64 subFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status)
-{
- Bit16s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig;
- Bit16s expDiff;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- bSig = extractFloat64Frac(b);
- bExp = extractFloat64Exp(b);
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- expDiff = aExp - bExp;
- aSig <<= 10;
- bSig <<= 10;
- if (0 < expDiff) goto aExpBigger;
- if (expDiff < 0) goto bExpBigger;
- if (aExp == 0x7FF) {
- if (aSig | bSig) return propagateFloat64NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- if (aExp == 0) {
- if (aSig | bSig) float_raise(status, float_flag_denormal);
- aExp = 1;
- bExp = 1;
- }
- if (bSig < aSig) goto aBigger;
- if (aSig < bSig) goto bBigger;
- return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0);
- bExpBigger:
- if (bExp == 0x7FF) {
- if (bSig) return propagateFloat64NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign ^ 1, 0x7FF, 0);
- }
- if ((bExp == 0) && bSig)
- float_raise(status, float_flag_denormal);
-
- if (aExp == 0) {
- if (aSig) float_raise(status, float_flag_denormal);
- ++expDiff;
- }
- else aSig |= BX_CONST64(0x4000000000000000);
-
- aSig = shift64RightJamming(aSig, -expDiff);
- bSig |= BX_CONST64(0x4000000000000000);
- bBigger:
- zSig = bSig - aSig;
- zExp = bExp;
- zSign ^= 1;
- goto normalizeRoundAndPack;
- aExpBigger:
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaN(a, b, status);
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if ((aExp == 0) && aSig)
- float_raise(status, float_flag_denormal);
-
- if (bExp == 0) {
- if (bSig) float_raise(status, float_flag_denormal);
- --expDiff;
- }
- else bSig |= BX_CONST64(0x4000000000000000);
-
- bSig = shift64RightJamming(bSig, expDiff);
- aSig |= BX_CONST64(0x4000000000000000);
- aBigger:
- zSig = aSig - bSig;
- zExp = aExp;
- normalizeRoundAndPack:
- --zExp;
- return normalizeRoundAndPackFloat64(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the double-precision floating-point values `a'
-| and `b'. The operation is performed according to the IEC/IEEE Standard for
-| Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_add(float64 a, float64 b, struct float_status_t *status)
-{
- int aSign = extractFloat64Sign(a);
- int bSign = extractFloat64Sign(b);
-
- if (aSign == bSign) {
- return addFloat64Sigs(a, b, aSign, status);
- }
- else {
- return subFloat64Sigs(a, b, aSign, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the double-precision floating-point values
-| `a' and `b'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_sub(float64 a, float64 b, struct float_status_t *status)
-{
- int aSign = extractFloat64Sign(a);
- int bSign = extractFloat64Sign(b);
-
- if (aSign == bSign) {
- return subFloat64Sigs(a, b, aSign, status);
- }
- else {
- return addFloat64Sigs(a, b, aSign, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the double-precision floating-point values
-| `a' and `b'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_mul(float64 a, float64 b, struct float_status_t *status)
-{
- int aSign, bSign, zSign;
- Bit16s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig0, zSig1;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
- bSig = extractFloat64Frac(b);
- bExp = extractFloat64Exp(b);
- bSign = extractFloat64Sign(b);
- zSign = aSign ^ bSign;
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- if (aExp == 0x7FF) {
- if (aSig || ((bExp == 0x7FF) && bSig)) {
- return propagateFloat64NaN(a, b, status);
- }
- if ((bExp | bSig) == 0) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign, 0x7FF, 0);
- }
- if (bExp == 0x7FF) {
- if (bSig) return propagateFloat64NaN(a, b, status);
- if ((aExp | aSig) == 0) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign, 0x7FF, 0);
- }
- if (aExp == 0) {
- if (aSig == 0) {
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign, 0, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- if (bSig == 0) return packFloat64(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(bSig, &bExp, &bSig);
- }
- zExp = aExp + bExp - 0x3FF;
- aSig = (aSig | BX_CONST64(0x0010000000000000))<<10;
- bSig = (bSig | BX_CONST64(0x0010000000000000))<<11;
- mul64To128(aSig, bSig, &zSig0, &zSig1);
- zSig0 |= (zSig1 != 0);
- if (0 <= (Bit64s) (zSig0<<1)) {
- zSig0 <<= 1;
- --zExp;
- }
- return roundAndPackFloat64(zSign, zExp, zSig0, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of dividing the double-precision floating-point value `a'
-| by the corresponding value `b'. The operation is performed according to
-| the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_div(float64 a, float64 b, struct float_status_t *status)
-{
- int aSign, bSign, zSign;
- Bit16s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig;
- Bit64u rem0, rem1;
- Bit64u term0, term1;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
- bSig = extractFloat64Frac(b);
- bExp = extractFloat64Exp(b);
- bSign = extractFloat64Sign(b);
- zSign = aSign ^ bSign;
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- if (bExp == 0) bSig = 0;
- }
-
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaN(a, b, status);
- if (bExp == 0x7FF) {
- if (bSig) return propagateFloat64NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign, 0x7FF, 0);
- }
- if (bExp == 0x7FF) {
- if (bSig) return propagateFloat64NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloat64(zSign, 0, 0);
- }
- if (bExp == 0) {
- if (bSig == 0) {
- if ((aExp | aSig) == 0) {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- float_raise(status, float_flag_divbyzero);
- return packFloat64(zSign, 0x7FF, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(bSig, &bExp, &bSig);
- }
- if (aExp == 0) {
- if (aSig == 0) return packFloat64(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(aSig, &aExp, &aSig);
- }
- zExp = aExp - bExp + 0x3FD;
- aSig = (aSig | BX_CONST64(0x0010000000000000))<<10;
- bSig = (bSig | BX_CONST64(0x0010000000000000))<<11;
- if (bSig <= (aSig + aSig)) {
- aSig >>= 1;
- ++zExp;
- }
- zSig = estimateDiv128To64(aSig, 0, bSig);
- if ((zSig & 0x1FF) <= 2) {
- mul64To128(bSig, zSig, &term0, &term1);
- sub128(aSig, 0, term0, term1, &rem0, &rem1);
- while ((Bit64s) rem0 < 0) {
- --zSig;
- add128(rem0, rem1, 0, bSig, &rem0, &rem1);
- }
- zSig |= (rem1 != 0);
- }
- return roundAndPackFloat64(zSign, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the square root of the double-precision floating-point value `a'.
-| The operation is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_sqrt(float64 a, struct float_status_t *status)
-{
- int aSign;
- Bit16s aExp, zExp;
- Bit64u aSig, zSig, doubleZSig;
- Bit64u rem0, rem1, term0, term1;
-
- aSig = extractFloat64Frac(a);
- aExp = extractFloat64Exp(a);
- aSign = extractFloat64Sign(a);
-
- if (aExp == 0x7FF) {
- if (aSig) return propagateFloat64NaNOne(a, status);
- if (! aSign) return a;
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
-
- if (get_denormals_are_zeros(status)) {
- if (aExp == 0) aSig = 0;
- }
-
- if (aSign) {
- if ((aExp | aSig) == 0) return packFloat64(aSign, 0, 0);
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
- if (aExp == 0) {
- if (aSig == 0) return 0;
- float_raise(status, float_flag_denormal);
- normalizeFloat64Subnormal(aSig, &aExp, &aSig);
- }
- zExp = ((aExp - 0x3FF)>>1) + 0x3FE;
- aSig |= BX_CONST64(0x0010000000000000);
- zSig = estimateSqrt32(aExp, (Bit32u)(aSig>>21));
- aSig <<= 9 - (aExp & 1);
- zSig = estimateDiv128To64(aSig, 0, zSig<<32) + (zSig<<30);
- if ((zSig & 0x1FF) <= 5) {
- doubleZSig = zSig<<1;
- mul64To128(zSig, zSig, &term0, &term1);
- sub128(aSig, 0, term0, term1, &rem0, &rem1);
- while ((Bit64s) rem0 < 0) {
- --zSig;
- doubleZSig -= 2;
- add128(rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1);
- }
- zSig |= ((rem0 | rem1) != 0);
- }
- return roundAndPackFloat64(0, zExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Determine double-precision floating-point number class
-*----------------------------------------------------------------------------*/
-
-float_class_t float64_class(float64 a)
-{
- Bit16s aExp = extractFloat64Exp(a);
- Bit64u aSig = extractFloat64Frac(a);
- int aSign = extractFloat64Sign(a);
-
- if(aExp == 0x7FF) {
- if (aSig == 0)
- return (aSign) ? float_negative_inf : float_positive_inf;
-
- return (aSig & BX_CONST64(0x0008000000000000)) ? float_QNaN : float_SNaN;
- }
-
- if(aExp == 0) {
- if (aSig == 0)
- return float_zero;
- return float_denormal;
- }
-
- return float_normalized;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two double precision floating point numbers. Returns
-| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
-| the value 'a' is less than the corresponding value `b',
-| 'float_relation_greater' if the value 'a' is greater than the corresponding
-| value `b', or 'float_relation_unordered' otherwise.
-*----------------------------------------------------------------------------*/
-
-int float64_compare(float64 a, float64 b, int quiet, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float64_denormal_to_zero(a);
- b = float64_denormal_to_zero(b);
- }
-
- float_class_t aClass = float64_class(a);
- float_class_t bClass = float64_class(b);
-
- if (aClass == float_SNaN || bClass == float_SNaN) {
- float_raise(status, float_flag_invalid);
- return float_relation_unordered;
- }
-
- if (aClass == float_QNaN || bClass == float_QNaN) {
- if (! quiet) float_raise(status, float_flag_invalid);
- return float_relation_unordered;
- }
-
- if (aClass == float_denormal || bClass == float_denormal) {
- float_raise(status, float_flag_denormal);
- }
-
- if ((a == b) || ((Bit64u) ((a | b)<<1) == 0)) return float_relation_equal;
-
- int aSign = extractFloat64Sign(a);
- int bSign = extractFloat64Sign(b);
- if (aSign != bSign)
- return (aSign) ? float_relation_less : float_relation_greater;
-
- if (aSign ^ (a < b)) return float_relation_less;
- return float_relation_greater;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two double precision floating point numbers and return the
-| smaller of them.
-*----------------------------------------------------------------------------*/
-
-float64 float64_min(float64 a, float64 b, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float64_denormal_to_zero(a);
- b = float64_denormal_to_zero(b);
- }
-
- return (float64_compare_two(a, b, status) == float_relation_less) ? a : b;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two double precision floating point numbers and return the
-| larger of them.
-*----------------------------------------------------------------------------*/
-
-float64 float64_max(float64 a, float64 b, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float64_denormal_to_zero(a);
- b = float64_denormal_to_zero(b);
- }
-
- return (float64_compare_two(a, b, status) == float_relation_greater) ? a : b;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two double precision floating point numbers and return the
-| smaller/larger of them. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status)
-{
- if (get_denormals_are_zeros(status)) {
- a = float64_denormal_to_zero(a);
- b = float64_denormal_to_zero(b);
- }
-
- if (float64_is_nan(a) || float64_is_nan(b)) {
- if (float64_is_signaling_nan(a)) {
- return propagateFloat64NaNOne(a, status);
- }
- if (float64_is_signaling_nan(b)) {
- return propagateFloat64NaNOne(b, status);
- }
- if (! float64_is_nan(b)) {
- if (float64_is_denormal(b))
- float_raise(status, float_flag_denormal);
- return b;
- }
- if (! float64_is_nan(a)) {
- if (float64_is_denormal(a))
- float_raise(status, float_flag_denormal);
- return a;
- }
- return propagateFloat64NaN(a, b, status);
- }
-
- float64 tmp_a = a, tmp_b = b;
- if (is_abs) {
- tmp_a &= ~BX_CONST64(0x8000000000000000); // clear the sign bit
- tmp_b &= ~BX_CONST64(0x8000000000000000);
- }
-
- int aSign = extractFloat64Sign(tmp_a);
- int bSign = extractFloat64Sign(tmp_b);
-
- if (float64_is_denormal(a) || float64_is_denormal(b))
- float_raise(status, float_flag_denormal);
-
- if (aSign != bSign) {
- if (! is_max) {
- return aSign ? a : b;
- } else {
- return aSign ? b : a;
- }
- } else {
- if (! is_max) {
- return (aSign ^ (tmp_a < tmp_b)) ? a : b;
- } else {
- return (aSign ^ (tmp_a < tmp_b)) ? b : a;
- }
- }
-}
-
-#ifdef FLOATX80
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the 32-bit two's complement integer `a'
-| to the extended double-precision floating-point format. The conversion
-| is performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 int32_to_floatx80(Bit32s a)
-{
- if (a == 0) return packFloatx80(0, 0, 0);
- int zSign = (a < 0);
- Bit32u absA = zSign ? -a : a;
- int shiftCount = countLeadingZeros32(absA) + 32;
- Bit64u zSig = absA;
- return packFloatx80(zSign, 0x403E - shiftCount, zSig< 0x401E) {
- float_raise(status, float_flag_invalid);
- return (Bit32s)(int32_indefinite);
- }
- if (aExp < 0x3FFF) {
- if (aExp || aSig) float_raise(status, float_flag_inexact);
- return 0;
- }
- shiftCount = 0x403E - aExp;
- savedASig = aSig;
- aSig >>= shiftCount;
- z = (Bit32s) aSig;
- if (aSign) z = -z;
- if ((z < 0) ^ aSign) {
- float_raise(status, float_flag_invalid);
- return (Bit32s)(int32_indefinite);
- }
- if ((aSig<>(-shiftCount);
- if ((Bit64u) (aSig<<(shiftCount & 63))) {
- float_raise(status, float_flag_inexact);
- }
- if (aSign) z = -z;
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the extended double-precision floating-
-| point value `a' to the single-precision floating-point format. The
-| conversion is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 floatx80_to_float32(floatx80 a, struct float_status_t *status)
-{
- Bit64u aSig = extractFloatx80Frac(a);
- Bit32s aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a))
- {
- float_raise(status, float_flag_invalid);
- return float32_default_nan;
- }
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1))
- return commonNaNToFloat32(floatx80ToCommonNaN(a, status));
-
- return packFloat32(aSign, 0xFF, 0);
- }
- aSig = shift64RightJamming(aSig, 33);
- if (aExp || aSig) aExp -= 0x3F81;
- return roundAndPackFloat32(aSign, aExp, (Bit32u) aSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the extended double-precision floating-
-| point value `a' to the double-precision floating-point format. The
-| conversion is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float64 floatx80_to_float64(floatx80 a, struct float_status_t *status)
-{
- Bit32s aExp;
- Bit64u aSig, zSig;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a))
- {
- float_raise(status, float_flag_invalid);
- return float64_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1)) {
- return commonNaNToFloat64(floatx80ToCommonNaN(a, status));
- }
- return packFloat64(aSign, 0x7FF, 0);
- }
- zSig = shift64RightJamming(aSig, 1);
- if (aExp || aSig) aExp -= 0x3C01;
- return roundAndPackFloat64(aSign, aExp, zSig, status);
-}
-
-/*----------------------------------------------------------------------------
-| Rounds the extended double-precision floating-point value `a' to an integer,
-| and returns the result as an extended double-precision floating-point
-| value. The operation is performed according to the IEC/IEEE Standard for
-| Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_round_to_int(floatx80 a, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- int aSign;
- Bit64u lastBitMask, roundBitsMask;
- int roundingMode = get_float_rounding_mode(status);
- floatx80 z;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a))
- {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- Bit32s aExp = extractFloatx80Exp(a);
- Bit64u aSig = extractFloatx80Frac(a);
- if (0x403E <= aExp) {
- if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) {
- return propagateFloatx80NaNOne(a, status);
- }
- return a;
- }
- if (aExp < 0x3FFF) {
- if (aExp == 0) {
- if ((aSig<<1) == 0) return a;
- float_raise(status, float_flag_denormal);
- }
- float_raise(status, float_flag_inexact);
- aSign = extractFloatx80Sign(a);
- switch (roundingMode) {
- case float_round_nearest_even:
- if ((aExp == 0x3FFE) && (Bit64u) (aSig<<1)) {
- set_float_rounding_up(status);
- return packFloatx80(aSign, 0x3FFF, BX_CONST64(0x8000000000000000));
- }
- break;
- case float_round_down:
- if (aSign) {
- set_float_rounding_up(status);
- return packFloatx80(1, 0x3FFF, BX_CONST64(0x8000000000000000));
- }
- else {
- return packFloatx80(0, 0, 0);
- }
- case float_round_up:
- if (aSign) {
- return packFloatx80(1, 0, 0);
- }
- else {
- set_float_rounding_up(status);
- return packFloatx80(0, 0x3FFF, BX_CONST64(0x8000000000000000));
- }
- }
- return packFloatx80(aSign, 0, 0);
- }
- lastBitMask = 1;
- lastBitMask <<= 0x403E - aExp;
- roundBitsMask = lastBitMask - 1;
- z = a;
- if (roundingMode == float_round_nearest_even) {
- z.fraction += lastBitMask>>1;
- if ((z.fraction & roundBitsMask) == 0) z.fraction &= ~lastBitMask;
- }
- else if (roundingMode != float_round_to_zero) {
- if (extractFloatx80Sign(z) ^ (roundingMode == float_round_up))
- z.fraction += roundBitsMask;
- }
- z.fraction &= ~roundBitsMask;
- if (z.fraction == 0) {
- z.exp++;
- z.fraction = BX_CONST64(0x8000000000000000);
- }
- if (z.fraction != a.fraction) {
- float_raise(status, float_flag_inexact);
- if (z.fraction > a.fraction || z.exp > a.exp)
- set_float_rounding_up(status);
- }
- return z;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the absolute values of the extended double-
-| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
-| negated before being returned. `zSign' is ignored if the result is a NaN.
-| The addition is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- Bit32s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig0, zSig1;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
- {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
- return propagateFloatx80NaN(a, b, status);
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (aExp == 0) {
- if (aSig == 0) {
- if ((bExp == 0) && bSig) {
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- }
- return roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, bExp, bSig, 0, status);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- if (bSig == 0)
- return roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, aExp, aSig, 0, status);
-
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- }
- Bit32s expDiff = aExp - bExp;
- zExp = aExp;
- if (0 < expDiff) {
- shift64ExtraRightJamming(bSig, 0, expDiff, &bSig, &zSig1);
- }
- else if (expDiff < 0) {
- shift64ExtraRightJamming(aSig, 0, -expDiff, &aSig, &zSig1);
- zExp = bExp;
- }
- else {
- zSig0 = aSig + bSig;
- zSig1 = 0;
- goto shiftRight1;
- }
- zSig0 = aSig + bSig;
- if ((Bit64s) zSig0 < 0) goto roundAndPack;
- shiftRight1:
- shift64ExtraRightJamming(zSig0, zSig1, 1, &zSig0, &zSig1);
- zSig0 |= BX_CONST64(0x8000000000000000);
- zExp++;
- roundAndPack:
- return
- roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, zExp, zSig0, zSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the absolute values of the extended
-| double-precision floating-point values `a' and `b'. If `zSign' is 1, the
-| difference is negated before being returned. `zSign' is ignored if the
-| result is a NaN. The subtraction is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- Bit32s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig0, zSig1;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
- {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloatx80(zSign ^ 1, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (aExp == 0) {
- if (aSig == 0) {
- if (bExp == 0) {
- if (bSig) {
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- return roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign ^ 1, bExp, bSig, 0, status);
- }
- return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0);
- }
- return roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign ^ 1, bExp, bSig, 0, status);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- if (bSig == 0)
- return roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, aExp, aSig, 0, status);
-
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- }
- Bit32s expDiff = aExp - bExp;
- if (0 < expDiff) {
- shift128RightJamming(bSig, 0, expDiff, &bSig, &zSig1);
- goto aBigger;
- }
- if (expDiff < 0) {
- shift128RightJamming(aSig, 0, -expDiff, &aSig, &zSig1);
- goto bBigger;
- }
- zSig1 = 0;
- if (bSig < aSig) goto aBigger;
- if (aSig < bSig) goto bBigger;
- return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0);
- bBigger:
- sub128(bSig, 0, aSig, zSig1, &zSig0, &zSig1);
- zExp = bExp;
- zSign ^= 1;
- goto normalizeRoundAndPack;
- aBigger:
- sub128(aSig, 0, bSig, zSig1, &zSig0, &zSig1);
- zExp = aExp;
- normalizeRoundAndPack:
- return
- normalizeRoundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, zExp, zSig0, zSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the extended double-precision floating-point
-| values `a' and `b'. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_add(floatx80 a, floatx80 b, struct float_status_t *status)
-{
- int aSign = extractFloatx80Sign(a);
- int bSign = extractFloatx80Sign(b);
-
- if (aSign == bSign)
- return addFloatx80Sigs(a, b, aSign, status);
- else
- return subFloatx80Sigs(a, b, aSign, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the extended double-precision floating-
-| point values `a' and `b'. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_sub(floatx80 a, floatx80 b, struct float_status_t *status)
-{
- int aSign = extractFloatx80Sign(a);
- int bSign = extractFloatx80Sign(b);
-
- if (aSign == bSign)
- return subFloatx80Sigs(a, b, aSign, status);
- else
- return addFloatx80Sigs(a, b, aSign, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the extended double-precision floating-
-| point values `a' and `b'. The operation is performed according to the
-| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_mul(floatx80 a, floatx80 b, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- int aSign, bSign, zSign;
- Bit32s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig0, zSig1;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
- {
- invalid:
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
- bSign = extractFloatx80Sign(b);
- zSign = aSign ^ bSign;
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) {
- return propagateFloatx80NaN(a, b, status);
- }
- if (bExp == 0) {
- if (bSig == 0) goto invalid;
- float_raise(status, float_flag_denormal);
- }
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (aExp == 0) {
- if (aSig == 0) goto invalid;
- float_raise(status, float_flag_denormal);
- }
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (aExp == 0) {
- if (aSig == 0) {
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloatx80(zSign, 0, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- if (bSig == 0) return packFloatx80(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- }
- zExp = aExp + bExp - 0x3FFE;
- mul64To128(aSig, bSig, &zSig0, &zSig1);
- if (0 < (Bit64s) zSig0) {
- shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
- --zExp;
- }
- return
- roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, zExp, zSig0, zSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of dividing the extended double-precision floating-point
-| value `a' by the corresponding value `b'. The operation is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_div(floatx80 a, floatx80 b, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- int aSign, bSign, zSign;
- Bit32s aExp, bExp, zExp;
- Bit64u aSig, bSig, zSig0, zSig1;
- Bit64u rem0, rem1, rem2, term0, term1, term2;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
- {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
- bSign = extractFloatx80Sign(b);
-
- zSign = aSign ^ bSign;
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- return packFloatx80(zSign, 0, 0);
- }
- if (bExp == 0) {
- if (bSig == 0) {
- if ((aExp | aSig) == 0) {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- float_raise(status, float_flag_divbyzero);
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- }
- if (aExp == 0) {
- if (aSig == 0) return packFloatx80(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- }
- zExp = aExp - bExp + 0x3FFE;
- rem1 = 0;
- if (bSig <= aSig) {
- shift128Right(aSig, 0, 1, &aSig, &rem1);
- ++zExp;
- }
- zSig0 = estimateDiv128To64(aSig, rem1, bSig);
- mul64To128(bSig, zSig0, &term0, &term1);
- sub128(aSig, rem1, term0, term1, &rem0, &rem1);
- while ((Bit64s) rem0 < 0) {
- --zSig0;
- add128(rem0, rem1, 0, bSig, &rem0, &rem1);
- }
- zSig1 = estimateDiv128To64(rem1, 0, bSig);
- if ((Bit64u) (zSig1<<1) <= 8) {
- mul64To128(bSig, zSig1, &term1, &term2);
- sub128(rem1, 0, term1, term2, &rem1, &rem2);
- while ((Bit64s) rem1 < 0) {
- --zSig1;
- add128(rem1, rem2, 0, bSig, &rem1, &rem2);
- }
- zSig1 |= ((rem1 | rem2) != 0);
- }
- return
- roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, zExp, zSig0, zSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the square root of the extended double-precision floating-point
-| value `a'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_sqrt(floatx80 a, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- int aSign;
- Bit32s aExp, zExp;
- Bit64u aSig0, aSig1, zSig0, zSig1, doubleZSig0;
- Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a))
- {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig0 = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig0<<1)) return propagateFloatx80NaNOne(a, status);
- if (! aSign) return a;
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- if (aSign) {
- if ((aExp | aSig0) == 0) return a;
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- if (aExp == 0) {
- if (aSig0 == 0) return packFloatx80(0, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
- }
- zExp = ((aExp - 0x3FFF)>>1) + 0x3FFF;
- zSig0 = estimateSqrt32(aExp, aSig0>>32);
- shift128Right(aSig0, 0, 2 + (aExp & 1), &aSig0, &aSig1);
- zSig0 = estimateDiv128To64(aSig0, aSig1, zSig0<<32) + (zSig0<<30);
- doubleZSig0 = zSig0<<1;
- mul64To128(zSig0, zSig0, &term0, &term1);
- sub128(aSig0, aSig1, term0, term1, &rem0, &rem1);
- while ((Bit64s) rem0 < 0) {
- --zSig0;
- doubleZSig0 -= 2;
- add128(rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1);
- }
- zSig1 = estimateDiv128To64(rem1, 0, doubleZSig0);
- if ((zSig1 & BX_CONST64(0x3FFFFFFFFFFFFFFF)) <= 5) {
- if (zSig1 == 0) zSig1 = 1;
- mul64To128(doubleZSig0, zSig1, &term1, &term2);
- sub128(rem1, 0, term1, term2, &rem1, &rem2);
- mul64To128(zSig1, zSig1, &term2, &term3);
- sub192(rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3);
- while ((Bit64s) rem1 < 0) {
- --zSig1;
- shortShift128Left(0, zSig1, 1, &term2, &term3);
- term3 |= 1;
- term2 |= doubleZSig0;
- add192(rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3);
- }
- zSig1 |= ((rem1 | rem2 | rem3) != 0);
- }
- shortShift128Left(0, zSig1, 1, &zSig0, &zSig1);
- zSig0 |= doubleZSig0;
- return
- roundAndPackFloatx80(get_float_rounding_precision(status),
- 0, zExp, zSig0, zSig1, status);
-}
-
-#endif
-
-#ifdef FLOAT128
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the extended double-precision floating-
-| point value `a' to the quadruple-precision floating-point format. The
-| conversion is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 floatx80_to_float128(floatx80 a, struct float_status_t *status)
-{
- Bit64u zSig0, zSig1;
-
- Bit64u aSig = extractFloatx80Frac(a);
- Bit32s aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
-
- if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1))
- return commonNaNToFloat128(floatx80ToCommonNaN(a, status));
-
- shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
- return packFloat128Four(aSign, aExp, zSig0, zSig1);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the quadruple-precision floating-point
-| value `a' to the extended double-precision floating-point format. The
-| conversion is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 float128_to_floatx80(float128 a, struct float_status_t *status)
-{
- Bit32s aExp;
- Bit64u aSig0, aSig1;
-
- aSig1 = extractFloat128Frac1(a);
- aSig0 = extractFloat128Frac0(a);
- aExp = extractFloat128Exp(a);
- int aSign = extractFloat128Sign(a);
-
- if (aExp == 0x7FFF) {
- if (aSig0 | aSig1)
- return commonNaNToFloatx80(float128ToCommonNaN(a, status));
-
- return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
-
- if (aExp == 0) {
- if ((aSig0 | aSig1) == 0) return packFloatx80(aSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1);
- }
- else aSig0 |= BX_CONST64(0x0001000000000000);
-
- shortShift128Left(aSig0, aSig1, 15, &aSig0, &aSig1);
- return roundAndPackFloatx80(80, aSign, aExp, aSig0, aSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the extended double-precision floating-
-| point value `a' and quadruple-precision floating point value `b'. The
-| operation is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- Bit32s aExp, bExp, zExp;
- Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2;
- int aSign, bSign, zSign;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a))
- {
- invalid:
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
- bSig0 = extractFloat128Frac0(b);
- bSig1 = extractFloat128Frac1(b);
- bExp = extractFloat128Exp(b);
- bSign = extractFloat128Sign(b);
-
- zSign = aSign ^ bSign;
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1)
- || ((bExp == 0x7FFF) && (bSig0 | bSig1)))
- {
- floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status));
- return propagateFloatx80NaN(a, r, status);
- }
- if (bExp == 0) {
- if ((bSig0 | bSig1) == 0) goto invalid;
- float_raise(status, float_flag_denormal);
- }
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (bExp == 0x7FFF) {
- if (bSig0 | bSig1) {
- floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status));
- return propagateFloatx80NaN(a, r, status);
- }
- if (aExp == 0) {
- if (aSig == 0) goto invalid;
- float_raise(status, float_flag_denormal);
- }
- return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (aExp == 0) {
- if (aSig == 0) {
- if ((bExp == 0) && (bSig0 | bSig1)) float_raise(status, float_flag_denormal);
- return packFloatx80(zSign, 0, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- }
- if (bExp == 0) {
- if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1);
- }
- else bSig0 |= BX_CONST64(0x0001000000000000);
-
- zExp = aExp + bExp - 0x3FFE;
- shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1);
- mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2);
- if (0 < (Bit64s) zSig0) {
- shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
- --zExp;
- }
- return
- roundAndPackFloatx80(get_float_rounding_precision(status),
- zSign, zExp, zSig0, zSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the absolute values of the quadruple-precision
-| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
-| before being returned. `zSign' is ignored if the result is a NaN.
-| The addition is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static float128 addFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status)
-{
- Bit32s aExp, bExp, zExp;
- Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
- Bit32s expDiff;
-
- aSig1 = extractFloat128Frac1(a);
- aSig0 = extractFloat128Frac0(a);
- aExp = extractFloat128Exp(a);
- bSig1 = extractFloat128Frac1(b);
- bSig0 = extractFloat128Frac0(b);
- bExp = extractFloat128Exp(b);
- expDiff = aExp - bExp;
-
- if (0 < expDiff) {
- if (aExp == 0x7FFF) {
- if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status);
- return a;
- }
- if (bExp == 0) --expDiff;
- else bSig0 |= BX_CONST64(0x0001000000000000);
- shift128ExtraRightJamming(bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2);
- zExp = aExp;
- }
- else if (expDiff < 0) {
- if (bExp == 0x7FFF) {
- if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status);
- return packFloat128Four(zSign, 0x7FFF, 0, 0);
- }
- if (aExp == 0) ++expDiff;
- else aSig0 |= BX_CONST64(0x0001000000000000);
- shift128ExtraRightJamming(aSig0, aSig1, 0, -expDiff, &aSig0, &aSig1, &zSig2);
- zExp = bExp;
- }
- else {
- if (aExp == 0x7FFF) {
- if (aSig0 | aSig1 | bSig0 | bSig1)
- return propagateFloat128NaN(a, b, status);
-
- return a;
- }
- add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1);
- if (aExp == 0) return packFloat128Four(zSign, 0, zSig0, zSig1);
- zSig2 = 0;
- zSig0 |= BX_CONST64(0x0002000000000000);
- zExp = aExp;
- goto shiftRight1;
- }
- aSig0 |= BX_CONST64(0x0001000000000000);
- add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1);
- --zExp;
- if (zSig0 < BX_CONST64(0x0002000000000000)) goto roundAndPack;
- ++zExp;
- shiftRight1:
- shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2);
- roundAndPack:
- return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the absolute values of the quadruple-
-| precision floating-point values `a' and `b'. If `zSign' is 1, the
-| difference is negated before being returned. `zSign' is ignored if the
-| result is a NaN. The subtraction is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-static float128 subFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status)
-{
- Bit32s aExp, bExp, zExp;
- Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
- Bit32s expDiff;
-
- aSig1 = extractFloat128Frac1(a);
- aSig0 = extractFloat128Frac0(a);
- aExp = extractFloat128Exp(a);
- bSig1 = extractFloat128Frac1(b);
- bSig0 = extractFloat128Frac0(b);
- bExp = extractFloat128Exp(b);
-
- expDiff = aExp - bExp;
- shortShift128Left(aSig0, aSig1, 14, &aSig0, &aSig1);
- shortShift128Left(bSig0, bSig1, 14, &bSig0, &bSig1);
- if (0 < expDiff) goto aExpBigger;
- if (expDiff < 0) goto bExpBigger;
- if (aExp == 0x7FFF) {
- if (aSig0 | aSig1 | bSig0 | bSig1)
- return propagateFloat128NaN(a, b, status);
-
- float_raise(status, float_flag_invalid);
- return float128_default_nan;
- }
- if (aExp == 0) {
- aExp = 1;
- bExp = 1;
- }
- if (bSig0 < aSig0) goto aBigger;
- if (aSig0 < bSig0) goto bBigger;
- if (bSig1 < aSig1) goto aBigger;
- if (aSig1 < bSig1) goto bBigger;
- return packFloat128(0, 0);
-
- bExpBigger:
- if (bExp == 0x7FFF) {
- if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status);
- return packFloat128Four(zSign ^ 1, 0x7FFF, 0, 0);
- }
- if (aExp == 0) ++expDiff;
- else {
- aSig0 |= BX_CONST64(0x4000000000000000);
- }
- shift128RightJamming(aSig0, aSig1, - expDiff, &aSig0, &aSig1);
- bSig0 |= BX_CONST64(0x4000000000000000);
- bBigger:
- sub128(bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1);
- zExp = bExp;
- zSign ^= 1;
- goto normalizeRoundAndPack;
- aExpBigger:
- if (aExp == 0x7FFF) {
- if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status);
- return a;
- }
- if (bExp == 0) --expDiff;
- else {
- bSig0 |= BX_CONST64(0x4000000000000000);
- }
- shift128RightJamming(bSig0, bSig1, expDiff, &bSig0, &bSig1);
- aSig0 |= BX_CONST64(0x4000000000000000);
- aBigger:
- sub128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1);
- zExp = aExp;
- normalizeRoundAndPack:
- --zExp;
- return normalizeRoundAndPackFloat128(zSign, zExp - 14, zSig0, zSig1, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of adding the quadruple-precision floating-point values
-| `a' and `b'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 float128_add(float128 a, float128 b, struct float_status_t *status)
-{
- int aSign = extractFloat128Sign(a);
- int bSign = extractFloat128Sign(b);
-
- if (aSign == bSign) {
- return addFloat128Sigs(a, b, aSign, status);
- }
- else {
- return subFloat128Sigs(a, b, aSign, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of subtracting the quadruple-precision floating-point
-| values `a' and `b'. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 float128_sub(float128 a, float128 b, struct float_status_t *status)
-{
- int aSign = extractFloat128Sign(a);
- int bSign = extractFloat128Sign(b);
-
- if (aSign == bSign) {
- return subFloat128Sigs(a, b, aSign, status);
- }
- else {
- return addFloat128Sigs(a, b, aSign, status);
- }
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of multiplying the quadruple-precision floating-point
-| values `a' and `b'. The operation is performed according to the IEC/IEEE
-| Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 float128_mul(float128 a, float128 b, struct float_status_t *status)
-{
- int aSign, bSign, zSign;
- Bit32s aExp, bExp, zExp;
- Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
-
- aSig1 = extractFloat128Frac1(a);
- aSig0 = extractFloat128Frac0(a);
- aExp = extractFloat128Exp(a);
- aSign = extractFloat128Sign(a);
- bSig1 = extractFloat128Frac1(b);
- bSig0 = extractFloat128Frac0(b);
- bExp = extractFloat128Exp(b);
- bSign = extractFloat128Sign(b);
-
- zSign = aSign ^ bSign;
- if (aExp == 0x7FFF) {
- if ((aSig0 | aSig1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) {
- return propagateFloat128NaN(a, b, status);
- }
- if ((bExp | bSig0 | bSig1) == 0) {
- float_raise(status, float_flag_invalid);
- return float128_default_nan;
- }
- return packFloat128Four(zSign, 0x7FFF, 0, 0);
- }
- if (bExp == 0x7FFF) {
- if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status);
- if ((aExp | aSig0 | aSig1) == 0) {
- float_raise(status, float_flag_invalid);
- return float128_default_nan;
- }
- return packFloat128Four(zSign, 0x7FFF, 0, 0);
- }
- if (aExp == 0) {
- if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1);
- }
- if (bExp == 0) {
- if ((bSig0 | bSig1) == 0) return packFloat128Four(zSign, 0, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1);
- }
- zExp = aExp + bExp - 0x4000;
- aSig0 |= BX_CONST64(0x0001000000000000);
- shortShift128Left(bSig0, bSig1, 16, &bSig0, &bSig1);
- mul128To256(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3);
- add128(zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1);
- zSig2 |= (zSig3 != 0);
- if (BX_CONST64(0x0002000000000000) <= zSig0) {
- shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2);
- ++zExp;
- }
- return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of dividing the quadruple-precision floating-point value
-| `a' by the corresponding value `b'. The operation is performed according to
-| the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 float128_div(float128 a, float128 b, struct float_status_t *status)
-{
- int aSign, bSign, zSign;
- Bit32s aExp, bExp, zExp;
- Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
- Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3;
-
- aSig1 = extractFloat128Frac1(a);
- aSig0 = extractFloat128Frac0(a);
- aExp = extractFloat128Exp(a);
- aSign = extractFloat128Sign(a);
- bSig1 = extractFloat128Frac1(b);
- bSig0 = extractFloat128Frac0(b);
- bExp = extractFloat128Exp(b);
- bSign = extractFloat128Sign(b);
-
- zSign = aSign ^ bSign;
- if (aExp == 0x7FFF) {
- if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status);
- if (bExp == 0x7FFF) {
- if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status);
- float_raise(status, float_flag_invalid);
- return float128_default_nan;
- }
- return packFloat128Four(zSign, 0x7FFF, 0, 0);
- }
- if (bExp == 0x7FFF) {
- if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status);
- return packFloat128Four(zSign, 0, 0, 0);
- }
- if (bExp == 0) {
- if ((bSig0 | bSig1) == 0) {
- if ((aExp | aSig0 | aSig1) == 0) {
- float_raise(status, float_flag_invalid);
- return float128_default_nan;
- }
- float_raise(status, float_flag_divbyzero);
- return packFloat128Four(zSign, 0x7FFF, 0, 0);
- }
- float_raise(status, float_flag_denormal);
- normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1);
- }
- if (aExp == 0) {
- if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1);
- }
- zExp = aExp - bExp + 0x3FFD;
- shortShift128Left(
- aSig0 | BX_CONST64(0x0001000000000000), aSig1, 15, &aSig0, &aSig1);
- shortShift128Left(
- bSig0 | BX_CONST64(0x0001000000000000), bSig1, 15, &bSig0, &bSig1);
- if (le128(bSig0, bSig1, aSig0, aSig1)) {
- shift128Right(aSig0, aSig1, 1, &aSig0, &aSig1);
- ++zExp;
- }
- zSig0 = estimateDiv128To64(aSig0, aSig1, bSig0);
- mul128By64To192(bSig0, bSig1, zSig0, &term0, &term1, &term2);
- sub192(aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2);
- while ((Bit64s) rem0 < 0) {
- --zSig0;
- add192(rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2);
- }
- zSig1 = estimateDiv128To64(rem1, rem2, bSig0);
- if ((zSig1 & 0x3FFF) <= 4) {
- mul128By64To192(bSig0, bSig1, zSig1, &term1, &term2, &term3);
- sub192(rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3);
- while ((Bit64s) rem1 < 0) {
- --zSig1;
- add192(rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3);
- }
- zSig1 |= ((rem1 | rem2 | rem3) != 0);
- }
- shift128ExtraRightJamming(zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2);
- return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the 64-bit two's complement integer `a' to
-| the quadruple-precision floating-point format. The conversion is performed
-| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float128 int64_to_float128(Bit64s a)
-{
- Bit64u zSig0, zSig1;
-
- if (a == 0) return packFloat128Four(0, 0, 0, 0);
- int zSign = (a < 0);
- Bit64u absA = zSign ? - a : a;
- Bit8u shiftCount = countLeadingZeros64(absA) + 49;
- Bit32s zExp = 0x406E - shiftCount;
- if (64 <= shiftCount) {
- zSig1 = 0;
- zSig0 = absA;
- shiftCount -= 64;
- }
- else {
- zSig1 = absA;
- zSig0 = 0;
- }
- shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
- return packFloat128Four(zSign, zExp, zSig0, zSig1);
-}
-
-#endif
diff --git a/src/cpu/softfloat/softfloat.h b/src/cpu/softfloat/softfloat.h
deleted file mode 100644
index 1d1b0f08f9..0000000000
--- a/src/cpu/softfloat/softfloat.h
+++ /dev/null
@@ -1,488 +0,0 @@
-/*============================================================================
-This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "config.h" /* generated by configure script from config.h.in */
-
-#ifndef _SOFTFLOAT_H_
-#define _SOFTFLOAT_H_
-
-#define FLOAT16
-#define FLOATX80
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point types.
-*----------------------------------------------------------------------------*/
-#ifdef FLOAT16
-typedef Bit16u float16;
-#endif
-typedef Bit32u float32;
-typedef Bit64u float64;
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point class.
-*----------------------------------------------------------------------------*/
-typedef enum {
- float_zero,
- float_SNaN,
- float_QNaN,
- float_negative_inf,
- float_positive_inf,
- float_denormal,
- float_normalized
-} float_class_t;
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point NaN operands handling mode.
-*----------------------------------------------------------------------------*/
-enum float_nan_handling_mode_t {
- float_larger_significand_nan = 0, // this mode used by x87 FPU
- float_first_operand_nan = 1 // this mode used by SSE
-};
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point rounding mode.
-*----------------------------------------------------------------------------*/
-enum float_round_t {
- float_round_nearest_even = 0,
- float_round_down = 1,
- float_round_up = 2,
- float_round_to_zero = 3
-};
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point exception flags.
-*----------------------------------------------------------------------------*/
-enum float_exception_flag_t {
- float_flag_invalid = 0x01,
- float_flag_denormal = 0x02,
- float_flag_divbyzero = 0x04,
- float_flag_overflow = 0x08,
- float_flag_underflow = 0x10,
- float_flag_inexact = 0x20
-};
-
-extern const unsigned float_all_exceptions_mask;
-
-#ifdef FLOATX80
-#define RAISE_SW_C1 0x0200
-#endif
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point ordering relations
-*----------------------------------------------------------------------------*/
-enum {
- float_relation_less = -1,
- float_relation_equal = 0,
- float_relation_greater = 1,
- float_relation_unordered = 2
-};
-
-/*----------------------------------------------------------------------------
-| Options to indicate which negations to perform in float*_muladd()
-| Using these differs from negating an input or output before calling
-| the muladd function in that this means that a NaN doesn't have its
-| sign bit inverted before it is propagated.
-*----------------------------------------------------------------------------*/
-enum {
- float_muladd_negate_c = 1,
- float_muladd_negate_product = 2,
- float_muladd_negate_result = float_muladd_negate_c | float_muladd_negate_product
-};
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point status structure.
-*----------------------------------------------------------------------------*/
-struct float_status_t
-{
-#ifdef FLOATX80
- int float_rounding_precision; /* floatx80 only */
-#endif
- int float_rounding_mode;
- int float_exception_flags;
- int float_exception_masks;
- int float_suppress_exception;
- int float_nan_handling_mode; /* flag register */
- int flush_underflow_to_zero; /* flag register */
- int denormals_are_zeros; /* flag register */
-};
-
-/*----------------------------------------------------------------------------
-| Routine to raise any or all of the software IEC/IEEE floating-point
-| exception flags.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE void float_raise(struct float_status_t *status, int flags)
-{
- status->float_exception_flags |= flags;
-}
-
-/*----------------------------------------------------------------------------
-| Returns raised IEC/IEEE floating-point exception flags.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int get_exception_flags(const struct float_status_t *status)
-{
- return status->float_exception_flags & ~status->float_suppress_exception;
-}
-
-/*----------------------------------------------------------------------------
-| Routine to check if any or all of the software IEC/IEEE floating-point
-| exceptions are masked.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int float_exception_masked(const struct float_status_t *status, int flag)
-{
- return status->float_exception_masks & flag;
-}
-
-/*----------------------------------------------------------------------------
-| Returns current floating point rounding mode specified by status word.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int get_float_rounding_mode(const struct float_status_t *status)
-{
- return status->float_rounding_mode;
-}
-
-/*----------------------------------------------------------------------------
-| Returns current floating point precision (floatx80 only).
-*----------------------------------------------------------------------------*/
-
-#ifdef FLOATX80
-BX_CPP_INLINE int get_float_rounding_precision(const struct float_status_t *status)
-{
- return status->float_rounding_precision;
-}
-#endif
-
-/*----------------------------------------------------------------------------
-| Returns current floating point NaN operands handling mode specified
-| by status word.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int get_float_nan_handling_mode(const struct float_status_t *status)
-{
- return status->float_nan_handling_mode;
-}
-
-/*----------------------------------------------------------------------------
-| Raise floating point precision lost up flag (floatx80 only).
-*----------------------------------------------------------------------------*/
-
-#ifdef FLOATX80
-BX_CPP_INLINE void set_float_rounding_up(struct float_status_t *status)
-{
- status->float_exception_flags |= RAISE_SW_C1;
-}
-#endif
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the feature is supported;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int get_denormals_are_zeros(const struct float_status_t *status)
-{
- return status->denormals_are_zeros;
-}
-
-/*----------------------------------------------------------------------------
-| Returns 1 if the feature is supported;
-| otherwise returns 0.
-*----------------------------------------------------------------------------*/
-
-BX_CPP_INLINE int get_flush_underflow_to_zero(const struct float_status_t *status)
-{
- return status->flush_underflow_to_zero;
-}
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE integer-to-floating-point conversion routines.
-*----------------------------------------------------------------------------*/
-float32 int32_to_float32(Bit32s, struct float_status_t *status);
-float64 int32_to_float64(Bit32s);
-float32 int64_to_float32(Bit64s, struct float_status_t *status);
-float64 int64_to_float64(Bit64s, struct float_status_t *status);
-
-float32 uint32_to_float32(Bit32u, struct float_status_t *status);
-float64 uint32_to_float64(Bit32u);
-float32 uint64_to_float32(Bit64u, struct float_status_t *status);
-float64 uint64_to_float64(Bit64u, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE single-precision conversion routines.
-*----------------------------------------------------------------------------*/
-Bit32s float32_to_int32(float32, struct float_status_t *status);
-Bit32s float32_to_int32_round_to_zero(float32, struct float_status_t *status);
-Bit64s float32_to_int64(float32, struct float_status_t *status);
-Bit64s float32_to_int64_round_to_zero(float32, struct float_status_t *status);
-Bit32u float32_to_uint32(float32, struct float_status_t *status);
-Bit32u float32_to_uint32_round_to_zero(float32, struct float_status_t *status);
-Bit64u float32_to_uint64(float32, struct float_status_t *status);
-Bit64u float32_to_uint64_round_to_zero(float32, struct float_status_t *status);
-float64 float32_to_float64(float32, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE single-precision operations.
-*----------------------------------------------------------------------------*/
-float32 float32_round_to_int(float32, Bit8u scale, struct float_status_t *status);
-float32 float32_add(float32, float32, struct float_status_t *status);
-float32 float32_sub(float32, float32, struct float_status_t *status);
-float32 float32_mul(float32, float32, struct float_status_t *status);
-float32 float32_div(float32, float32, struct float_status_t *status);
-float32 float32_sqrt(float32, struct float_status_t *status);
-float32 float32_frc(float32, struct float_status_t *status);
-float32 float32_muladd(float32, float32, float32, int flags, struct float_status_t *status);
-float32 float32_scalef(float32, float32, struct float_status_t *status);
-int float32_compare(float32, float32, int quiet, struct float_status_t *status);
-
-BX_CPP_INLINE float32 float32_round_to_int_one(float32 a, struct float_status_t *status)
-{
- return float32_round_to_int(a, 0, status);
-}
-
-BX_CPP_INLINE float32 float32_fmadd(float32 a, float32 b, float32 c, struct float_status_t *status)
-{
- return float32_muladd(a, b, c, 0, status);
-}
-
-BX_CPP_INLINE float32 float32_fmsub(float32 a, float32 b, float32 c, struct float_status_t *status)
-{
- return float32_muladd(a, b, c, float_muladd_negate_c, status);
-}
-
-BX_CPP_INLINE float32 float32_fnmadd(float32 a, float32 b, float32 c, struct float_status_t *status)
-{
- return float32_muladd(a, b, c, float_muladd_negate_product, status);
-}
-
-BX_CPP_INLINE float32 float32_fnmsub(float32 a, float32 b, float32 c, struct float_status_t *status)
-{
- return float32_muladd(a, b, c, float_muladd_negate_result, status);
-}
-
-BX_CPP_INLINE int float32_compare_two(float32 a, float32 b, struct float_status_t *status)
-{
- return float32_compare(a, b, 0, status);
-}
-
-BX_CPP_INLINE int float32_compare_quiet(float32 a, float32 b, struct float_status_t *status)
-{
- return float32_compare(a, b, 1, status);
-}
-
-float_class_t float32_class(float32);
-
-float32 float32_min(float32 a, float32 b, struct float_status_t *status);
-float32 float32_max(float32 a, float32 b, struct float_status_t *status);
-
-float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status);
-float32 float32_getexp(float32 a, struct float_status_t *status);
-float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE double-precision conversion routines.
-*----------------------------------------------------------------------------*/
-Bit32s float64_to_int32(float64, struct float_status_t *status);
-Bit32s float64_to_int32_round_to_zero(float64, struct float_status_t *status);
-Bit64s float64_to_int64(float64, struct float_status_t *status);
-Bit64s float64_to_int64_round_to_zero(float64, struct float_status_t *status);
-Bit32u float64_to_uint32(float64, struct float_status_t *status);
-Bit32u float64_to_uint32_round_to_zero(float64, struct float_status_t *status);
-Bit64u float64_to_uint64(float64, struct float_status_t *status);
-Bit64u float64_to_uint64_round_to_zero(float64, struct float_status_t *status);
-float32 float64_to_float32(float64, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE double-precision operations.
-*----------------------------------------------------------------------------*/
-float64 float64_round_to_int(float64, Bit8u scale, struct float_status_t *status);
-float64 float64_add(float64, float64, struct float_status_t *status);
-float64 float64_sub(float64, float64, struct float_status_t *status);
-float64 float64_mul(float64, float64, struct float_status_t *status);
-float64 float64_div(float64, float64, struct float_status_t *status);
-float64 float64_sqrt(float64, struct float_status_t *status);
-float64 float64_frc(float64, struct float_status_t *status);
-float64 float64_muladd(float64, float64, float64, int flags, struct float_status_t *status);
-float64 float64_scalef(float64, float64, struct float_status_t *status);
-int float64_compare(float64, float64, int quiet, struct float_status_t *status);
-
-BX_CPP_INLINE float64 float64_round_to_int_one(float64 a, struct float_status_t *status)
-{
- return float64_round_to_int(a, 0, status);
-}
-
-BX_CPP_INLINE float64 float64_fmadd(float64 a, float64 b, float64 c, struct float_status_t *status)
-{
- return float64_muladd(a, b, c, 0, status);
-}
-
-BX_CPP_INLINE float64 float64_fmsub(float64 a, float64 b, float64 c, struct float_status_t *status)
-{
- return float64_muladd(a, b, c, float_muladd_negate_c, status);
-}
-
-BX_CPP_INLINE float64 float64_fnmadd(float64 a, float64 b, float64 c, struct float_status_t *status)
-{
- return float64_muladd(a, b, c, float_muladd_negate_product, status);
-}
-
-BX_CPP_INLINE float64 float64_fnmsub(float64 a, float64 b, float64 c, struct float_status_t *status)
-{
- return float64_muladd(a, b, c, float_muladd_negate_result, status);
-}
-
-BX_CPP_INLINE int float64_compare_two(float64 a, float64 b, struct float_status_t *status)
-{
- return float64_compare(a, b, 0, status);
-}
-
-BX_CPP_INLINE int float64_compare_quiet(float64 a, float64 b, struct float_status_t *status)
-{
- return float64_compare(a, b, 1, status);
-}
-
-float_class_t float64_class(float64);
-
-float64 float64_min(float64 a, float64 b, struct float_status_t *status);
-float64 float64_max(float64 a, float64 b, struct float_status_t *status);
-
-float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status);
-float64 float64_getexp(float64 a, struct float_status_t *status);
-float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv);
-
-#ifdef FLOAT16
-float32 float16_to_float32(float16, struct float_status_t *status);
-float16 float32_to_float16(float32, struct float_status_t *status);
-
-float_class_t float16_class(float16);
-#endif
-
-#ifdef FLOATX80
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE floating-point types.
-*----------------------------------------------------------------------------*/
-
-#ifdef BX_BIG_ENDIAN
-typedef struct floatx80 { // leave alignment to compiler
- Bit16u exp;
- Bit64u fraction;
-}; floatx80
-#else
-typedef struct floatx80 {
- Bit64u fraction;
- Bit16u exp;
-} floatx80;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE integer-to-floating-point conversion routines.
-*----------------------------------------------------------------------------*/
-floatx80 int32_to_floatx80(Bit32s);
-floatx80 int64_to_floatx80(Bit64s);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE extended double-precision conversion routines.
-*----------------------------------------------------------------------------*/
-floatx80 float32_to_floatx80(float32, struct float_status_t *status);
-floatx80 float64_to_floatx80(float64, struct float_status_t *status);
-
-Bit32s floatx80_to_int32(floatx80, struct float_status_t *status);
-Bit32s floatx80_to_int32_round_to_zero(floatx80, struct float_status_t *status);
-Bit64s floatx80_to_int64(floatx80, struct float_status_t *status);
-Bit64s floatx80_to_int64_round_to_zero(floatx80, struct float_status_t *status);
-
-float32 floatx80_to_float32(floatx80, struct float_status_t *status);
-float64 floatx80_to_float64(floatx80, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE extended double-precision operations.
-*----------------------------------------------------------------------------*/
-floatx80 floatx80_round_to_int(floatx80, struct float_status_t *status);
-floatx80 floatx80_add(floatx80, floatx80, struct float_status_t *status);
-floatx80 floatx80_sub(floatx80, floatx80, struct float_status_t *status);
-floatx80 floatx80_mul(floatx80, floatx80, struct float_status_t *status);
-floatx80 floatx80_div(floatx80, floatx80, struct float_status_t *status);
-floatx80 floatx80_sqrt(floatx80, struct float_status_t *status);
-
-float_class_t floatx80_class(floatx80);
-#ifdef __cplusplus
-}
-#endif
-#endif /* FLOATX80 */
-
-#ifdef FLOAT128
-
-#ifdef BX_BIG_ENDIAN
-typedef struct float128 {
- Bit64u hi, lo;
-} float128;
-#else
-typedef struct float128 {
- Bit64u lo, hi;
-} float128;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE quadruple-precision conversion routines.
-*----------------------------------------------------------------------------*/
-float128 floatx80_to_float128(floatx80 a, struct float_status_t *status);
-floatx80 float128_to_floatx80(float128 a, struct float_status_t *status);
-
-float128 int64_to_float128(Bit64s a);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE extended double-precision operations.
-*----------------------------------------------------------------------------*/
-floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE quadruple-precision operations.
-*----------------------------------------------------------------------------*/
-float128 float128_add(float128 a, float128 b, struct float_status_t *status);
-float128 float128_sub(float128 a, float128 b, struct float_status_t *status);
-float128 float128_mul(float128 a, float128 b, struct float_status_t *status);
-float128 float128_div(float128 a, float128 b, struct float_status_t *status);
-#ifdef __cplusplus
-}
-#endif
-#endif /* FLOAT128 */
-
-#endif
diff --git a/src/cpu/softfloat/softfloat16.cc b/src/cpu/softfloat/softfloat16.cc
deleted file mode 100644
index 8c17d3a86e..0000000000
--- a/src/cpu/softfloat/softfloat16.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-/*============================================================================
-This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
-Package, Release 2b.
-
-Written by John R. Hauser. This work was made possible in part by the
-International Computer Science Institute, located at Suite 600, 1947 Center
-Street, Berkeley, California 94704. Funding was partially provided by the
-National Science Foundation under grant MIP-9311980. The original version
-of this code was written as part of a project to build a fixed-point vector
-processor in collaboration with the University of California at Berkeley,
-overseen by Profs. Nelson Morgan and John Wawrzynek. More information
-is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
-arithmetic/SoftFloat.html'.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Adapted for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "softfloat.h"
-
-#ifdef FLOAT16
-
-#include "softfloat-round-pack.h"
-#include "softfloat-specialize.h"
-#include "softfloat-macros.h"
-
-/*----------------------------------------------------------------------------
-| Determine half-precision floating-point number class
-*----------------------------------------------------------------------------*/
-
-float_class_t float16_class(float16 a)
-{
- Bit16s aExp = extractFloat16Exp(a);
- Bit16u aSig = extractFloat16Frac(a);
- int aSign = extractFloat16Sign(a);
-
- if(aExp == 0x1F) {
- if (aSig == 0)
- return (aSign) ? float_negative_inf : float_positive_inf;
-
- return (aSig & 0x200) ? float_QNaN : float_SNaN;
- }
-
- if(aExp == 0) {
- if (aSig == 0) return float_zero;
- return float_denormal;
- }
-
- return float_normalized;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the half-precision floating-point value
-| `a' to the single-precision floating-point format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float32 float16_to_float32(float16 a, struct float_status_t *status)
-{
- Bit16u aSig = extractFloat16Frac(a);
- Bit16s aExp = extractFloat16Exp(a);
- int aSign = extractFloat16Sign(a);
-
- if (aExp == 0x1F) {
- if (aSig) return commonNaNToFloat32(float16ToCommonNaN(a, status));
- return packFloat32(aSign, 0xFF, 0);
- }
- if (aExp == 0) {
- // ignore denormals_are_zeros flag
- if (aSig == 0) return packFloat32(aSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloat16Subnormal(aSig, &aExp, &aSig);
- --aExp;
- }
-
- return packFloat32(aSign, aExp + 0x70, ((Bit32u) aSig)<<13);
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the single-precision floating-point value
-| `a' to the half-precision floating-point format. The conversion is
-| performed according to the IEC/IEEE Standard for Binary Floating-Point
-| Arithmetic.
-*----------------------------------------------------------------------------*/
-
-float16 float32_to_float16(float32 a, struct float_status_t *status)
-{
- Bit32u aSig = extractFloat32Frac(a);
- Bit16s aExp = extractFloat32Exp(a);
- int aSign = extractFloat32Sign(a);
-
- if (aExp == 0xFF) {
- if (aSig) return commonNaNToFloat16(float32ToCommonNaN(a, status));
- return packFloat16(aSign, 0x1F, 0);
- }
- if (aExp == 0) {
- if (get_denormals_are_zeros(status)) aSig = 0;
- if (aSig == 0) return packFloat16(aSign, 0, 0);
- float_raise(status, float_flag_denormal);
- }
-
- aSig = shift32RightJamming(aSig, 9);
- Bit16u zSig = (Bit16u) aSig;
- if (aExp || zSig) {
- zSig |= 0x4000;
- aExp -= 0x71;
- }
-
- return roundAndPackFloat16(aSign, aExp, zSig, status);
-}
-
-#endif
diff --git a/src/cpu/softfloat/softfloatx80.cc b/src/cpu/softfloat/softfloatx80.cc
deleted file mode 100644
index 3ac3e61b3b..0000000000
--- a/src/cpu/softfloat/softfloatx80.cc
+++ /dev/null
@@ -1,367 +0,0 @@
-/*============================================================================
-This source file is an extension to the SoftFloat IEC/IEEE Floating-point
-Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
-floating point emulation.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Written for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#include "softfloatx80.h"
-#include "softfloat-round-pack.h"
-#include "softfloat-macros.h"
-
-const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-const floatx80 Const_Z = packFloatx80(0, 0x0000, 0);
-const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
-const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe));
-const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc));
-const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
-const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799));
-const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac));
-const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000));
-
-/*----------------------------------------------------------------------------
-| Commonly used single-precision floating point constants
-*----------------------------------------------------------------------------*/
-const float32 float32_negative_inf = 0xff800000;
-const float32 float32_positive_inf = 0x7f800000;
-const float32 float32_negative_zero = 0x80000000;
-const float32 float32_positive_zero = 0x00000000;
-const float32 float32_negative_one = 0xbf800000;
-const float32 float32_positive_one = 0x3f800000;
-const float32 float32_max_float = 0x7f7fffff;
-const float32 float32_min_float = 0xff7fffff;
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated single-precision NaN.
-*----------------------------------------------------------------------------*/
-const float32 float32_default_nan = 0xffc00000;
-
-/*----------------------------------------------------------------------------
-| Commonly used single-precision floating point constants
-*----------------------------------------------------------------------------*/
-const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000);
-const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000);
-const float64 float64_negative_zero = BX_CONST64(0x8000000000000000);
-const float64 float64_positive_zero = BX_CONST64(0x0000000000000000);
-const float64 float64_negative_one = BX_CONST64(0xbff0000000000000);
-const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000);
-const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff);
-const float64 float64_min_float = BX_CONST64(0xffefffffffffffff);
-
-/*----------------------------------------------------------------------------
-| The pattern for a default generated double-precision NaN.
-*----------------------------------------------------------------------------*/
-const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000);
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the extended double-precision floating-
-| point value `a' to the 16-bit two's complement integer format. The
-| conversion is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic - which means in particular that the conversion
-| is rounded according to the current rounding mode. If `a' is a NaN or the
-| conversion overflows, the integer indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit16s floatx80_to_int16(floatx80 a, struct float_status_t *status)
-{
- if (floatx80_is_unsupported(a)) {
- float_raise(status, float_flag_invalid);
- return int16_indefinite;
- }
-
- Bit32s v32 = floatx80_to_int32(a, status);
-
- if ((v32 > 32767) || (v32 < -32768)) {
- status->float_exception_flags = float_flag_invalid; // throw away other flags
- return int16_indefinite;
- }
-
- return (Bit16s) v32;
-}
-
-/*----------------------------------------------------------------------------
-| Returns the result of converting the extended double-precision floating-
-| point value `a' to the 16-bit two's complement integer format. The
-| conversion is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic, except that the conversion is always rounded
-| toward zero. If `a' is a NaN or the conversion overflows, the integer
-| indefinite value is returned.
-*----------------------------------------------------------------------------*/
-
-Bit16s floatx80_to_int16_round_to_zero(floatx80 a, struct float_status_t *status)
-{
- if (floatx80_is_unsupported(a)) {
- float_raise(status, float_flag_invalid);
- return int16_indefinite;
- }
-
- Bit32s v32 = floatx80_to_int32_round_to_zero(a, status);
-
- if ((v32 > 32767) || (v32 < -32768)) {
- status->float_exception_flags = float_flag_invalid; // throw away other flags
- return int16_indefinite;
- }
-
- return (Bit16s) v32;
-}
-
-/*----------------------------------------------------------------------------
-| Separate the source extended double-precision floating point value `a'
-| into its exponent and significand, store the significant back to the
-| 'a' and return the exponent. The operation performed is a superset of
-| the IEC/IEEE recommended logb(x) function.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- Bit64u aSig = extractFloatx80Frac(*a);
- Bit32s aExp = extractFloatx80Exp(*a);
- int aSign = extractFloatx80Sign(*a);
-
- if (floatx80_is_unsupported(*a))
- {
- float_raise(status, float_flag_invalid);
- *a = floatx80_default_nan;
- return *a;
- }
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1))
- {
- *a = propagateFloatx80NaNOne(*a, status);
- return *a;
- }
- return packFloatx80(0, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (aExp == 0)
- {
- if (aSig == 0) {
- float_raise(status, float_flag_divbyzero);
- *a = packFloatx80(aSign, 0, 0);
- return packFloatx80(1, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- }
-
- a->exp = (aSign << 15) + 0x3FFF;
- a->fraction = aSig;
- return int32_to_floatx80(aExp - 0x3FFF);
-}
-
-/*----------------------------------------------------------------------------
-| Scales extended double-precision floating-point value in operand `a' by
-| value `b'. The function truncates the value in the second operand 'b' to
-| an integral value and adds that value to the exponent of the operand 'a'.
-| The operation performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status)
-{
-/*----------------------------------------------------------------------------
-| The pattern for a default generated extended double-precision NaN.
-*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
-
- Bit32s aExp, bExp;
- Bit64u aSig, bSig;
-
- // handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
- {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
-
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
- int bSign = extractFloatx80Sign(b);
-
- if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
- {
- return propagateFloatx80NaN(a, b, status);
- }
- if ((bExp == 0x7FFF) && bSign) {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- return a;
- }
- if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- if ((aExp | aSig) == 0) {
- if (! bSign) {
- float_raise(status, float_flag_invalid);
- return floatx80_default_nan;
- }
- return a;
- }
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
- if (bSign) return packFloatx80(aSign, 0, 0);
- return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000));
- }
- if (aExp == 0) {
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
- if (aSig == 0) return a;
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
- if (bExp < 0x3FFF)
- return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0, status);
- }
- if (bExp == 0) {
- if (bSig == 0) return a;
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
- }
-
- if (bExp > 0x400E) {
- /* generate appropriate overflow/underflow */
- return roundAndPackFloatx80(80, aSign,
- bSign ? -0x3FFF : 0x7FFF, aSig, 0, status);
- }
-
- if (bExp < 0x3FFF) return a;
-
- int shiftCount = 0x403E - bExp;
- bSig >>= shiftCount;
- Bit32s scale = (Bit32s) bSig;
- if (bSign) scale = -scale; /* -32768..32767 */
- return
- roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0, status);
-}
-
-/*----------------------------------------------------------------------------
-| Determine extended-precision floating-point number class.
-*----------------------------------------------------------------------------*/
-
-float_class_t floatx80_class(floatx80 a)
-{
- Bit32s aExp = extractFloatx80Exp(a);
- Bit64u aSig = extractFloatx80Frac(a);
-
- if(aExp == 0) {
- if (aSig == 0)
- return float_zero;
-
- /* denormal or pseudo-denormal */
- return float_denormal;
- }
-
- /* valid numbers have the MS bit set */
- if (!(aSig & BX_CONST64(0x8000000000000000)))
- return float_SNaN; /* report unsupported as SNaNs */
-
- if(aExp == 0x7fff) {
- int aSign = extractFloatx80Sign(a);
-
- if (((Bit64u) (aSig<< 1)) == 0)
- return (aSign) ? float_negative_inf : float_positive_inf;
-
- return (aSig & BX_CONST64(0x4000000000000000)) ? float_QNaN : float_SNaN;
- }
-
- return float_normalized;
-}
-
-/*----------------------------------------------------------------------------
-| Compare between two extended precision floating point numbers. Returns
-| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
-| the value 'a' is less than the corresponding value `b',
-| 'float_relation_greater' if the value 'a' is greater than the corresponding
-| value `b', or 'float_relation_unordered' otherwise.
-*----------------------------------------------------------------------------*/
-
-int floatx80_compare(floatx80 a, floatx80 b, int quiet, struct float_status_t *status)
-{
- float_class_t aClass = floatx80_class(a);
- float_class_t bClass = floatx80_class(b);
-
- if (aClass == float_SNaN || bClass == float_SNaN)
- {
- /* unsupported reported as SNaN */
- float_raise(status, float_flag_invalid);
- return float_relation_unordered;
- }
-
- if (aClass == float_QNaN || bClass == float_QNaN) {
- if (! quiet) float_raise(status, float_flag_invalid);
- return float_relation_unordered;
- }
-
- if (aClass == float_denormal || bClass == float_denormal) {
- float_raise(status, float_flag_denormal);
- }
-
- int aSign = extractFloatx80Sign(a);
- int bSign = extractFloatx80Sign(b);
-
- if (aClass == float_zero) {
- if (bClass == float_zero) return float_relation_equal;
- return bSign ? float_relation_greater : float_relation_less;
- }
-
- if (bClass == float_zero || aSign != bSign) {
- return aSign ? float_relation_less : float_relation_greater;
- }
-
- Bit64u aSig = extractFloatx80Frac(a);
- Bit32s aExp = extractFloatx80Exp(a);
- Bit64u bSig = extractFloatx80Frac(b);
- Bit32s bExp = extractFloatx80Exp(b);
-
- if (aClass == float_denormal)
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
-
- if (bClass == float_denormal)
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
-
- if (aExp == bExp && aSig == bSig)
- return float_relation_equal;
-
- int less_than =
- aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig)))
- : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig)));
-
- if (less_than) return float_relation_less;
- return float_relation_greater;
-}
-
-
-int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status)
-{
- return floatx80_compare(a, b, 0, status);
-}
-
-int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status)
-{
- return floatx80_compare(a, b, 1, status);
-}
diff --git a/src/cpu/softfloat/softfloatx80.h b/src/cpu/softfloat/softfloatx80.h
deleted file mode 100644
index 1f96141b4c..0000000000
--- a/src/cpu/softfloat/softfloatx80.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*============================================================================
-This source file is an extension to the SoftFloat IEC/IEEE Floating-point
-Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
-floating point emulation.
-
-THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
-been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
-RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
-AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
-COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
-EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
-INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
-OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
-
-Derivative works are acceptable, even for commercial purposes, so long as
-(1) the source code for the derivative work includes prominent notice that
-the work is derivative, and (2) the source code includes prominent notice with
-these four paragraphs for those parts of this code that are retained.
-=============================================================================*/
-
-/*============================================================================
- * Written for Bochs (x86 achitecture simulator) by
- * Stanislav Shwartsman [sshwarts at sourceforge net]
- * ==========================================================================*/
-
-#ifndef _SOFTFLOATX80_EXTENSIONS_H_
-#define _SOFTFLOATX80_EXTENSIONS_H_
-
-#include "softfloat.h"
-#include "softfloat-specialize.h"
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE integer-to-floating-point conversion routines.
-*----------------------------------------------------------------------------*/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-Bit16s floatx80_to_int16(floatx80, struct float_status_t *status);
-Bit16s floatx80_to_int16_round_to_zero(floatx80, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE extended double-precision operations.
-*----------------------------------------------------------------------------*/
-
-floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status);
-floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status);
-int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status);
-int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status);
-floatx80 f2xm1(floatx80 a, struct float_status_t *status);
-floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status);
-floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status);
-floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE extended double-precision trigonometric functions.
-*----------------------------------------------------------------------------*/
-
-int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status);
-int fsin(floatx80 *a, struct float_status_t *status);
-int fcos(floatx80 *a, struct float_status_t *status);
-int ftan(floatx80 *a, struct float_status_t *status);
-
-/*----------------------------------------------------------------------------
-| Software IEC/IEEE extended double-precision compare.
-*----------------------------------------------------------------------------*/
-
-int floatx80_compare(floatx80, floatx80, int quiet, struct float_status_t *status);
-int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status);
-int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*-----------------------------------------------------------------------------
-| Calculates the absolute value of the extended double-precision floating-point
-| value `a'. The operation is performed according to the IEC/IEEE Standard
-| for Binary Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-#ifdef __cplusplus
-BX_CPP_INLINE floatx80& floatx80_abs(floatx80 ®)
-#else
-BX_CPP_INLINE floatx80 floatx80_abs(floatx80 reg)
-#endif
-{
- reg.exp &= 0x7FFF;
- return reg;
-}
-
-/*-----------------------------------------------------------------------------
-| Changes the sign of the extended double-precision floating-point value 'a'.
-| The operation is performed according to the IEC/IEEE Standard for Binary
-| Floating-Point Arithmetic.
-*----------------------------------------------------------------------------*/
-
-#ifdef __cplusplus
-BX_CPP_INLINE floatx80& floatx80_chs(floatx80 ®)
-#else
-BX_CPP_INLINE floatx80 floatx80_chs(floatx80 reg)
-#endif
-{
- reg.exp ^= 0x8000;
- return reg;
-}
-
-/*-----------------------------------------------------------------------------
-| Commonly used extended double-precision floating-point constants.
-*----------------------------------------------------------------------------*/
-
-extern const floatx80 Const_Z;
-extern const floatx80 Const_1;
-extern const floatx80 Const_L2T;
-extern const floatx80 Const_L2E;
-extern const floatx80 Const_PI;
-extern const floatx80 Const_LG2;
-extern const floatx80 Const_LN2;
-extern const floatx80 Const_INF;
-#endif
diff --git a/src/cpu/softfloat3e/CMakeLists.txt b/src/cpu/softfloat3e/CMakeLists.txt
new file mode 100644
index 0000000000..9f9ae06792
--- /dev/null
+++ b/src/cpu/softfloat3e/CMakeLists.txt
@@ -0,0 +1,57 @@
+#
+# 86Box A hypervisor and IBM PC system emulator that specializes in
+# running old operating systems and software designed for IBM
+# PC systems and compatibles from 1981 through fairly recent
+# system designs based on the PCI bus.
+#
+# This file is part of the 86Box distribution.
+#
+# CMake build script.
+#
+# Authors: David Hrdlička,
+#
+# Copyright 2020-2021 David Hrdlička.
+#
+
+add_library(softfloat3e OBJECT primitives.c softfloat-specialize.c
+ extF80_addsub.cc extF80_class.cc extF80_compare.cc
+ extF80_div.cc extF80_extract.cc extF80_mul.cc extF80_rem.cc extF80_roundToInt.cc
+ extF80_scale.cc extF80_sqrt.cc extF80_to_f16.cc extF80_to_f32.cc extF80_to_f64.cc
+ extF80_to_f128.cc extF80_to_i32.cc extF80_to_i32_r_minMag.cc extF80_to_i64.cc
+ extF80_to_i64_r_minMag.cc extF80_to_ui32.cc extF80_to_ui32_r_minMag.cc extF80_to_ui64.cc
+ extF80_to_ui64_r_minMag.cc f16_addsub.c f16_class.c f16_compare.c f16_div.c f16_getExp.c
+ f16_getMant.c f16_minmax.c f16_mul.c f16_mulAdd.c f16_range.c f16_roundToInt.c
+ f16_sqrt.c f16_to_extF80.cc f16_to_f32.c f16_to_f64.c f16_to_i32.c f16_to_i32_r_minMag.c
+ f16_to_i64.c f16_to_i64_r_minMag.c f16_to_ui32.c f16_to_ui32_r_minMag.c f16_to_ui64.c
+ f16_to_ui64_r_minMag.c f32_addsub.c f32_class.c f32_compare.c f32_div.c f32_frc.c
+ f32_getExp.c f32_getMant.c f32_minmax.c f32_mul.c f32_mulAdd.c f32_range.c
+ f32_roundToInt.c f32_scalef.c f32_sqrt.c f32_to_extF80.cc f32_to_f16.c f32_to_f64.c
+ f32_to_f128.cc f32_to_i32.c f32_to_i32_r_minMag.c f32_to_i64.c f32_to_i64_r_minMag.c
+ f32_to_ui32.c f32_to_ui32_r_minMag.c f32_to_ui64.c f32_to_ui64_r_minMag.c f64_addsub.c
+ f64_class.c f64_compare.c f64_div.c f64_frc.c f64_getExp.c f64_getMant.c f64_minmax.c
+ f64_mul.c f64_mulAdd.c f64_range.c f64_roundToInt.c f64_scalef.c f64_sqrt.c f64_to_extF80.cc
+ f64_to_f16.c f64_to_f32.c f64_to_f128.cc f64_to_i32.c f64_to_i32_r_minMag.c f64_to_i64.c
+ f64_to_i64_r_minMag.c f64_to_ui32.c f64_to_ui32_r_minMag.c f64_to_ui64.c f64_to_ui64_r_minMag.c
+ f128_addsub.cc f128_div.cc f128_mul.cc f128_mulAdd.cc f128_roundToInt.cc f128_to_extF80.cc
+ f128_to_f32.cc f128_to_f64.cc f128_to_i32.cc f128_to_i32_r_minMag.cc f128_to_i64.cc
+ f128_to_i64_r_minMag.cc f128_to_ui32.cc f128_to_ui32_r_minMag.cc f128_to_ui64.cc
+ f128_to_ui64_r_minMag.cc i32_to_extF80.cc i32_to_f16.c i32_to_f32.c i32_to_f64.c
+ i32_to_f128.cc i64_to_extF80.cc i64_to_f16.c i64_to_f32.c i64_to_f64.c i64_to_f128.cc
+ isNaN.cc isSignalingNaN.cc s_add128.cc s_add256M.c s_addMagsExtF80.cc s_addMagsF16.c
+ s_addMagsF32.c s_addMagsF64.c s_addMagsF128.cc s_approxRecip_1Ks.c s_approxRecipSqrt_1Ks.c
+ s_approxRecipSqrt32_1.c s_commonNaNToExtF80UI.cc s_commonNaNToF16UI.c s_commonNaNToF32UI.c
+ s_commonNaNToF64UI.c s_commonNaNToF128UI.cc s_countLeadingZeros8.c s_countLeadingZeros16.c
+ s_countLeadingZeros32.c s_countLeadingZeros64.c s_eq128.c s_le128.c s_lt128.c
+ s_mul64ByShifted32To128.cc s_mul64To128.cc s_mul128By32.cc s_mul128To256M.cc
+ s_normRoundPackToExtF80.cc s_normRoundPackToF16.c s_normRoundPackToF32.c s_normRoundPackToF64.c
+ s_normRoundPackToF128.cc s_normSubnormalExtF80Sig.cc s_normSubnormalF16Sig.c
+ s_normSubnormalF32Sig.c s_normSubnormalF64Sig.c s_normSubnormalF128Sig.cc s_packToExtF80.cc
+ s_propagateNaNExtF80UI.cc s_propagateNaNF16UI.c s_propagateNaNF32UI.c s_propagateNaNF64UI.c
+ s_propagateNaNF128UI.cc s_roundPackToExtF80.cc s_roundPackToF16.c s_roundPackToF32.c
+ s_roundPackToF64.c s_roundPackToF128.cc s_roundToI32.c s_roundToI64.c s_roundToUI32.c
+ s_roundToUI64.c s_shiftRightJam32.c s_shiftRightJam64.c s_shiftRightJam64Extra.c
+ s_shiftRightJam256M.c s_shortShiftLeft128.cc s_shortShiftRight128.cc s_shortShiftRightJam64.c
+ s_shortShiftRightJam64Extra.c s_sub128.cc s_sub256M.c s_subMagsExtF80.cc s_subMagsF16.c
+ s_subMagsF32.c s_subMagsF64.c s_subMagsF128.cc ui32_to_extF80.cc ui32_to_f16.c ui32_to_f32.c
+ ui32_to_f64.c ui32_to_f128.cc ui64_to_extF80.cc ui64_to_f16.c ui64_to_f32.c ui64_to_f64.c
+ ui64_to_f128.cc f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc poly.cc consts.cc)
\ No newline at end of file
diff --git a/src/cpu/softfloat3e/COPYING.txt b/src/cpu/softfloat3e/COPYING.txt
new file mode 100644
index 0000000000..b5690face0
--- /dev/null
+++ b/src/cpu/softfloat3e/COPYING.txt
@@ -0,0 +1,37 @@
+
+License for Berkeley SoftFloat Release 3e
+
+John R. Hauser
+2018 January 20
+
+The following applies to the whole of SoftFloat Release 3e as well as to
+each source file individually.
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 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.
+
diff --git a/src/cpu/softfloat3e/README.html b/src/cpu/softfloat3e/README.html
new file mode 100644
index 0000000000..e695c2bd82
--- /dev/null
+++ b/src/cpu/softfloat3e/README.html
@@ -0,0 +1,49 @@
+
+
+
+
+Berkeley SoftFloat Package Overview
+
+
+
+
+Package Overview for Berkeley SoftFloat Release 3e
+
+
+John R. Hauser
+2018 January 20
+
+
+
+Berkeley SoftFloat is a software implementation of binary floating-point that
+conforms to the IEEE Standard for Floating-Point Arithmetic.
+SoftFloat is distributed in the form of C source code.
+Building the SoftFloat sources generates a library file (typically
+softfloat.a
or libsoftfloat.a
) containing the
+floating-point subroutines.
+
+
+
+The SoftFloat package is documented in the following files in the
+doc
subdirectory:
+
+
+
+Other files in the package comprise the source code for SoftFloat.
+
+
+
+
diff --git a/src/cpu/softfloat3e/README.txt b/src/cpu/softfloat3e/README.txt
new file mode 100644
index 0000000000..1613c76718
--- /dev/null
+++ b/src/cpu/softfloat3e/README.txt
@@ -0,0 +1,21 @@
+
+Package Overview for Berkeley SoftFloat Release 3e
+
+John R. Hauser
+2018 January 20
+
+Berkeley SoftFloat is a software implementation of binary floating-point
+that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat
+is distributed in the form of C source code. Building the SoftFloat sources
+generates a library file (typically "softfloat.a" or "libsoftfloat.a")
+containing the floating-point subroutines.
+
+The SoftFloat package is documented in the following files in the "doc"
+subdirectory:
+
+ SoftFloat.html Documentation for using the SoftFloat functions.
+ SoftFloat-source.html Documentation for building SoftFloat.
+ SoftFloat-history.html History of the major changes to SoftFloat.
+
+Other files in the package comprise the source code for SoftFloat.
+
diff --git a/src/cpu/softfloat3e/config.h b/src/cpu/softfloat3e/config.h
new file mode 100644
index 0000000000..9febce2424
--- /dev/null
+++ b/src/cpu/softfloat3e/config.h
@@ -0,0 +1,14 @@
+#ifndef EMU_SF_CONFIG_H
+#define EMU_SF_CONFIG_H
+
+/*----------------------------------------------------------------------------
+| The `LIT64' macro takes as its argument a textual integer literal and
+| if necessary ``marks'' the literal as having a 64-bit integer type.
+| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
+| appended with the letters `LL' standing for `long long', which is `gcc's
+| name for the 64-bit integer type. Some compilers may allow `LIT64' to be
+| defined as the identity macro: `#define LIT64( a ) a'.
+*----------------------------------------------------------------------------*/
+#define BX_CONST64(a) a##LL
+
+#endif /*EMU_SF_CONFIG_H*/
diff --git a/src/cpu/softfloat3e/consts.cc b/src/cpu/softfloat3e/consts.cc
new file mode 100644
index 0000000000..235a039965
--- /dev/null
+++ b/src/cpu/softfloat3e/consts.cc
@@ -0,0 +1,51 @@
+/*============================================================================
+
+This C header 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
+#include
+#include <86box/86box.h>
+#include "../cpu.h"
+
+#include "softfloat-specialize.h"
+
+const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+const floatx80 Const_Z = packFloatx80(0, 0x0000, 0);
+const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
+const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe));
+const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc));
+const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
+const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799));
+const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac));
+const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000));
diff --git a/src/cpu/softfloat3e/doc/SoftFloat-history.html b/src/cpu/softfloat3e/doc/SoftFloat-history.html
new file mode 100644
index 0000000000..d81c6bc5a2
--- /dev/null
+++ b/src/cpu/softfloat3e/doc/SoftFloat-history.html
@@ -0,0 +1,258 @@
+
+
+
+
+Berkeley SoftFloat History
+
+
+
+
+History of Berkeley SoftFloat, to Release 3e
+
+
+John R. Hauser
+2018 January 20
+
+
+
+Release 3e (2018 January)
+
+
+
+-
+Changed the default numeric code for optional rounding mode
odd
+(round to odd, also known as jamming) from 5 to 6.
+
+ -
+Modified the behavior of rounding mode
odd
when rounding to an
+integer value (either conversion to an integer format or a
+‘roundToInt
’ function).
+Previously, for those cases only, rounding mode odd
acted the same
+as rounding to minimum magnitude.
+Now all operations are rounded consistently.
+
+ -
+Fixed some errors in the specialization code modeling Intel x86 floating-point,
+specifically the integers returned on invalid operations and the propagation of
+NaN payloads in a few rare cases.
+
+
-
+Added specialization code modeling ARM floating-point, conforming to VFPv2 or
+later.
+
+
-
+Added an example target for ARM processors.
+
+
-
+Fixed a minor bug whereby function
f16_to_ui64
might return a
+different integer than expected in the case that the floating-point operand is
+negative.
+
+ -
+Added example target-specific optimization for GCC, employing GCC instrinsics
+and support for 128-bit integer arithmetic.
+
+
-
+Made other minor improvements.
+
+
+
+
+Release 3d (2017 August)
+
+
+
+-
+Fixed bugs in the square root functions for 64-bit
+double-precision, 80-bit double-extended-precision, and
+128-bit quadruple-precision.
+For 64-bit double-precision (
f64_sqrt
), the result
+could sometimes be off by 1 unit in the last place
+(1 ulp) from what it should be.
+For the larger formats, the square root could be wrong in a large portion of
+the less-significant bits.
+(A bug in f128_sqrt
was first reported by Alexei Sibidanov.)
+
+
+
+
+Release 3c (2017 February)
+
+
+
+-
+Added optional rounding mode
odd
(round to odd, also known as
+jamming).
+
+ -
+Corrected the documentation concerning non-canonical representations in
+80-bit double-extended-precision.
+
+
+
+
+Release 3b (2016 July)
+
+
+
+-
+Implemented the common 16-bit “half-precision”
+floating-point format (
float16_t
).
+
+ -
+Made the integer values returned on invalid conversions to integer formats
+be determined by the port-specific specialization instead of being the same for
+all ports.
+
+
-
+Added preprocessor macro
THREAD_LOCAL
to allow the floating-point
+state (modes and exception flags) to be made per-thread.
+
+ -
+Modified the provided Makefiles to allow some options to be overridden from the
+
make
command.
+
+ -
+Made other minor improvements.
+
+
+
+
+Release 3a (2015 October)
+
+
+
+-
+Replaced the license text supplied by the University of California, Berkeley.
+
+
+
+
+Release 3 (2015 February)
+
+
+
+-
+Complete rewrite, funded by the University of California, Berkeley, and
+consequently having a different use license than earlier releases.
+Major changes included renaming most types and functions, upgrading some
+algorithms, restructuring the source files, and making SoftFloat into a true
+library.
+
+
-
+Added functions to convert between floating-point and unsigned integers, both
+32-bit and 64-bit (
uint32_t
and
+uint64_t
).
+
+ -
+Added functions for fused multiply-add, for all supported floating-point
+formats except 80-bit double-extended-precision.
+
+
-
+Added support for a fifth rounding mode,
near_maxMag
(round to
+nearest, with ties to maximum magnitude, away from zero).
+
+ -
+Dropped the
timesoftfloat
program (now part of the Berkeley
+TestFloat package).
+
+
+
+
+Release 2c (2015 January)
+
+
+
+-
+Fixed mistakes affecting some 64-bit processors.
+
+
-
+Further improved the documentation and the wording for the legal restrictions
+on using SoftFloat releases through 2c (not applicable to
+Release 3 or later).
+
+
+
+
+Release 2b (2002 May)
+
+
+
+-
+Made minor updates to the documentation, including improved wording for the
+legal restrictions on using SoftFloat.
+
+
+
+
+Release 2a (1998 December)
+
+
+
+-
+Added functions to convert between 64-bit integers
+(
int64
) and all supported floating-point formats.
+
+ -
+Fixed a bug in all 64-bit-version square root functions except
+
float32_sqrt
that caused the result sometimes to be off by
+1 unit in the last place (1 ulp) from what it should
+be.
+(Bug discovered by Paul Donahue.)
+
+ -
+Improved the Makefiles.
+
+
+
+Release 2 (1997 June)
+
+
+
+-
+Created the 64-bit (
bits64
) version, adding the
+floatx80
and float128
formats.
+
+ -
+Changed the source directory structure, splitting the sources into a
+
bits32
and a bits64
version.
+Renamed environment.h
to milieu.h
to avoid confusion
+with environment variables.
+
+ -
+Fixed a small error that caused
float64_round_to_int
often to
+round the wrong way in nearest/even mode when the operand was between
+220 and 221 and halfway between two integers.
+
+
+
+
+Release 1a (1996 July)
+
+
+
+-
+Corrected a mistake that caused borderline underflow cases not to raise the
+underflow flag when they should have.
+(Problem reported by Doug Priest.)
+
+
-
+Added the
float_detect_tininess
variable to control whether
+tininess is detected before or after rounding.
+
+
+
+
+Release 1 (1996 July)
+
+
+
+-
+Original release, based on work done for the International Computer Science
+Institute (ICSI) in Berkeley, California.
+
+
+
+
+
+
diff --git a/src/cpu/softfloat3e/doc/SoftFloat-source.html b/src/cpu/softfloat3e/doc/SoftFloat-source.html
new file mode 100644
index 0000000000..4ff9d4c45a
--- /dev/null
+++ b/src/cpu/softfloat3e/doc/SoftFloat-source.html
@@ -0,0 +1,686 @@
+
+
+
+
+Berkeley SoftFloat Source Documentation
+
+
+
+
+Berkeley SoftFloat Release 3e: Source Documentation
+
+
+John R. Hauser
+2018 January 20
+
+
+
+Contents
+
+
+
+
+
+1. Introduction |
+2. Limitations |
+3. Acknowledgments and License |
+4. SoftFloat Package Directory Structure |
+5. Issues for Porting SoftFloat to a New Target |
+
+ |
+ 5.1. Standard Headers <stdbool.h> and
+ <stdint.h> |
+
+ | 5.2. Specializing Floating-Point Behavior |
+ | 5.3. Macros for Build Options |
+ | 5.4. Adapting a Template Target Directory |
+
+ | 5.5. Target-Specific Optimization of Primitive Functions |
+
+6. Testing SoftFloat |
+
+ 7. Providing SoftFloat as a Common Library for Applications |
+
+8. Contact Information |
+
+
+
+
+1. Introduction
+
+
+This document gives information needed for compiling and/or porting Berkeley
+SoftFloat, a library of C functions implementing binary floating-point
+conforming to the IEEE Standard for Floating-Point Arithmetic.
+For basic documentation about SoftFloat refer to
+SoftFloat.html
.
+
+
+
+The source code for SoftFloat is intended to be relatively machine-independent
+and should be compilable with any ISO-Standard C compiler that also supports
+64-bit integers.
+SoftFloat has been successfully compiled with the GNU C Compiler
+(gcc
) for several platforms.
+
+
+
+Release 3 of SoftFloat was a complete rewrite relative to
+Release 2 or earlier.
+Changes to the interface of SoftFloat functions are documented in
+SoftFloat.html
.
+The current version of SoftFloat is Release 3e.
+
+
+
+2. Limitations
+
+
+SoftFloat assumes the computer has an addressable byte size of either 8 or
+16 bits.
+(Nearly all computers in use today have 8-bit bytes.)
+
+
+
+SoftFloat is written in C and is designed to work with other C code.
+The C compiler used must conform at a minimum to the 1989 ANSI standard for the
+C language (same as the 1990 ISO standard) and must in addition support basic
+arithmetic on 64-bit integers.
+Earlier releases of SoftFloat included implementations of 32-bit
+single-precision and 64-bit double-precision floating-point that
+did not require 64-bit integers, but this option is not supported
+starting with Release 3.
+Since 1999, ISO standards for C have mandated compiler support for
+64-bit integers.
+A compiler conforming to the 1999 C Standard or later is recommended but not
+strictly required.
+
+
+
+C Standard header files <stdbool.h>
and
+<stdint.h>
are required for defining standard Boolean and
+integer types.
+If these headers are not supplied with the C compiler, minimal substitutes must
+be provided.
+SoftFloat’s dependence on these headers is detailed later in
+section 5.1, Standard Headers <stdbool.h>
+and <stdint.h>
.
+
+
+
+3. Acknowledgments and License
+
+
+The SoftFloat package was written by me, John R. Hauser.
+Release 3 of SoftFloat was a completely new implementation
+supplanting earlier releases.
+The project to create Release 3 (now through 3e) was
+done in the employ of the University of California, Berkeley, within the
+Department of Electrical Engineering and Computer Sciences, first for the
+Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab.
+The work was officially overseen by Prof. Krste Asanovic, with funding provided
+by these sources:
+
+
+
+
+
+
+Par Lab: |
+ |
+
+Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery
+(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia,
+NVIDIA, Oracle, and Samsung.
+ |
+
+
+ASPIRE Lab: |
+ |
+
+DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from
+ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA,
+Oracle, and Samsung.
+ |
+
+
+
+
+
+
+The following applies to the whole of SoftFloat Release 3e as well
+as to each source file individually.
+
+
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 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:
+
+
+-
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions, and the following disclaimer.
+
+
+ -
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions, and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+
+ -
+
+Neither the name of the University 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.
+
+
+
+4. SoftFloat Package Directory Structure
+
+
+Because SoftFloat is targeted to multiple platforms, its source code is
+slightly scattered between target-specific and target-independent directories
+and files.
+The supplied directory structure is as follows:
+
+
+doc
+source
+ include
+ 8086
+ 8086-SSE
+ ARM-VFPv2
+ ARM-VFPv2-defaultNaN
+build
+ template-FAST_INT64
+ template-not-FAST_INT64
+ Linux-386-GCC
+ Linux-386-SSE2-GCC
+ Linux-x86_64-GCC
+ Linux-ARM-VFPv2-GCC
+ Win32-MinGW
+ Win32-SSE2-MinGW
+ Win64-MinGW-w64
+
+
+The majority of the SoftFloat sources are provided in the source
+directory.
+The include
subdirectory contains several header files
+(unsurprisingly), while the other subdirectories of source
contain
+source files that specialize the floating-point behavior to match particular
+processor families:
+
+
+8086
+-
+Intel’s older, 8087-derived floating-point, extended to all supported
+floating-point types
+
+8086-SSE
+-
+Intel’s x86 processors with Streaming SIMD Extensions (SSE) and later
+compatible extensions, having 8087 behavior for 80-bit
+double-extended-precision (
extFloat80_t
) and SSE behavior for
+other floating-point types
+
+ARM-VFPv2
+-
+ARM’s VFPv2 or later floating-point, with NaN payload propagation
+
+ARM-VFPv2-defaultNaN
+-
+ARM’s VFPv2 or later floating-point, with the “default NaN”
+option
+
+
+
+If other specializations are attempted, these would be expected to be other
+subdirectories of source
alongside the ones listed above.
+Specialization is covered later, in section 5.2, Specializing
+Floating-Point Behavior.
+
+
+
+The build
directory is intended to contain a subdirectory for each
+target platform for which a build of the SoftFloat library may be created.
+For each build target, the target’s subdirectory is where all derived
+object files and the completed SoftFloat library (typically
+softfloat.a
or libsoftfloat.a
) are created.
+The two template
subdirectories are not actual build targets but
+contain sample files for creating new target directories.
+(The meaning of FAST_INT64
will be explained later.)
+
+
+
+Ignoring the template
directories, the supplied target directories
+are intended to follow a naming system of
+<execution-environment>-<compiler>
.
+For the example targets,
+<execution-environment>
is
+Linux-386
, Linux-386-SSE2
,
+Linux-x86_64
,
+Linux-ARM-VFPv2
, Win32
,
+Win32-SSE2
, or Win64
, and
+<compiler>
is GCC
,
+MinGW
, or MinGW-w64
.
+
+
+
+All of the supplied target directories are merely examples that may or may not
+be correct for compiling on any particular system.
+Despite requests, there are currently no plans to include and maintain in the
+SoftFloat package the build files needed for a great many users’
+compilation environments, which can span a huge range of operating systems,
+compilers, and other tools.
+
+
+
+As supplied, each target directory contains two files:
+
+
+Makefile
+platform.h
+
+
+The provided Makefile
is written for GNU make
.
+A build of SoftFloat for the specific target is begun by executing the
+make
command with the target directory as the current directory.
+A completely different build tool can be used if an appropriate
+Makefile
equivalent is created.
+
+
+
+The platform.h
header file exists to provide a location for
+additional C declarations specific to the build target.
+Every C source file of SoftFloat contains a #include
for
+platform.h
.
+In many cases, the contents of platform.h
can be as simple as one
+or two lines of code.
+At the other extreme, to get maximal performance from SoftFloat, it may be
+desirable to include in header platform.h
(directly or via
+#include
) declarations for numerous target-specific optimizations.
+Such possibilities are discussed in the next section, Issues for Porting
+SoftFloat to a New Target.
+If the target’s compiler or library has bugs or other shortcomings,
+workarounds for these issues may also be possible with target-specific
+declarations in platform.h
, avoiding the need to modify the main
+SoftFloat sources.
+
+
+
+5. Issues for Porting SoftFloat to a New Target
+
+5.1. Standard Headers <stdbool.h>
and <stdint.h>
+
+
+The SoftFloat sources make use of standard headers
+<stdbool.h>
and <stdint.h>
, which have
+been part of the ISO C Standard Library since 1999.
+With any recent compiler, these standard headers are likely to be supported,
+even if the compiler does not claim complete conformance to the latest ISO C
+Standard.
+For older or nonstandard compilers, substitutes for
+<stdbool.h>
and <stdint.h>
may need to be
+created.
+SoftFloat depends on these names from <stdbool.h>
:
+
+
+bool
+true
+false
+
+
+and on these names from <stdint.h>
:
+
+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+UINT64_C
+INT64_C
+uint_least8_t
+uint_fast8_t
+uint_fast16_t
+uint_fast32_t
+uint_fast64_t
+int_fast8_t
+int_fast16_t
+int_fast32_t
+int_fast64_t
+
+
+
+
+
+5.2. Specializing Floating-Point Behavior
+
+
+The IEEE Floating-Point Standard allows for some flexibility in a conforming
+implementation, particularly concerning NaNs.
+The SoftFloat source
directory is supplied with some
+specialization subdirectories containing possible definitions for this
+implementation-specific behavior.
+For example, the 8086
and 8086-SSE
+subdirectories have source files that specialize SoftFloat’s behavior to
+match that of Intel’s x86 line of processors.
+The files in a specialization subdirectory must determine:
+
+-
+whether tininess for underflow is detected before or after rounding by default;
+
-
+how signaling NaNs are distinguished from quiet NaNs;
+
-
+what (if anything) special happens when exceptions are raised;
+
-
+the default generated quiet NaNs;
+
-
+how NaNs are propagated from function inputs to output; and
+
-
+the integer results returned when conversions to integer type raise the
+invalid exception.
+
+
+
+
+As provided, the build process for a target expects to involve exactly
+one specialization directory that defines all of these
+implementation-specific details for the target.
+A specialization directory such as 8086
is expected to contain a
+header file called specialize.h
, together with whatever other
+source files are needed to complete the specialization.
+
+
+
+A new build target may use an existing specialization, such as the ones
+provided by the 8086
and 8086-SSE
+subdirectories.
+If a build target needs a new specialization, different from any existing ones,
+it is recommended that a new specialization directory be created for this
+purpose.
+The specialize.h
header file from any of the provided
+specialization subdirectories can be used as a model for what definitions are
+needed.
+
+
+
+5.3. Macros for Build Options
+
+
+The SoftFloat source files adapt the floating-point implementation according to
+several C preprocessor macros:
+
+
+LITTLEENDIAN
+-
+Must be defined for little-endian machines; must not be defined for big-endian
+machines.
+
INLINE
+-
+Specifies the sequence of tokens used to indicate that a C function should be
+inlined.
+If macro
INLINE_LEVEL
is defined with a value of 1 or higher, this
+macro must be defined; otherwise, this macro is ignored and need not be
+defined.
+For compilers that conform to the C Standard’s rules for inline
+functions, this macro can be defined as the single keyword inline
.
+For other compilers that follow a convention pre-dating the standardization of
+inline
, this macro may need to be defined to extern
+inline
.
+ THREAD_LOCAL
+-
+Can be defined to a sequence of tokens that, when appearing at the start of a
+variable declaration, indicates to the C compiler that the variable is
+per-thread, meaning that each execution thread gets its own separate
+instance of the variable.
+This macro is used in header
softfloat.h
in the declarations of
+variables softfloat_roundingMode
,
+softfloat_detectTininess
, extF80_roundingPrecision
,
+and softfloat_exceptionFlags
.
+If macro THREAD_LOCAL
is left undefined, these variables will
+default to being ordinary global variables.
+Depending on the compiler, possible valid definitions of this macro include
+_Thread_local
and __thread
.
+
+
+SOFTFLOAT_ROUND_ODD
+-
+Can be defined to enable support for optional rounding mode
+
softfloat_round_odd
.
+
+
+INLINE_LEVEL
+-
+Can be defined to an integer to determine the degree of inlining requested of
+the compiler.
+Larger numbers request that more inlining be done.
+If this macro is not defined or is defined to a value less than 1
+(zero or negative), no inlining is requested.
+The maximum effective value is no higher than 5.
+Defining this macro to a value greater than 5 is the same as defining it
+to 5.
+
SOFTFLOAT_FAST_INT64
+-
+Can be defined to indicate that the build target’s implementation of
+64-bit arithmetic is efficient.
+For newer 64-bit processors, this macro should usually be defined.
+For very small microprocessors whose buses and registers are 8-bit
+or 16-bit in size, this macro should usually not be defined.
+Whether this macro should be defined for a 32-bit processor may
+depend on the target machine and the applications that will use SoftFloat.
+
SOFTFLOAT_FAST_DIV32TO16
+-
+Can be defined to indicate that the target’s division operator
+in C (written as
/
) is reasonably efficient for
+dividing a 32-bit unsigned integer by a 16-bit
+unsigned integer.
+Setting this macro may affect the performance of function f16_div
.
+ SOFTFLOAT_FAST_DIV64TO32
+-
+Can be defined to indicate that the target’s division operator
+in C (written as
/
) is reasonably efficient for
+dividing a 64-bit unsigned integer by a 32-bit
+unsigned integer.
+Setting this macro may affect the performance of division, remainder, and
+square root operations other than f16_div
.
+
+
+
+
+
+Following the usual custom for C, for most of these macros (all
+except INLINE
, THREAD_LOCAL
, and
+INLINE_LEVEL
), the content of any definition is irrelevant;
+what matters is a macro’s effect on #ifdef
directives.
+
+
+
+It is recommended that any definitions of macros LITTLEENDIAN
,
+INLINE
, and THREAD_LOCAL
be made in a build
+target’s platform.h
header file, because these macros are
+expected to be determined inflexibly by the target machine and compiler.
+The other five macros select options and control optimization, and thus might
+be better located in the target’s Makefile (or its equivalent).
+
+
+
+5.4. Adapting a Template Target Directory
+
+
+In the build
directory, two template
subdirectories
+provide models for new target directories.
+Two different templates exist because different functions are needed in the
+SoftFloat library depending on whether macro SOFTFLOAT_FAST_INT64
+is defined.
+If macro SOFTFLOAT_FAST_INT64
will be defined,
+template-FAST_INT64
is the template to use;
+otherwise, template-not-FAST_INT64
is the appropriate
+template.
+A new target directory can be created by copying the correct template directory
+and editing the files inside.
+To avoid confusion, it would be wise to refrain from editing the files within a
+template directory directly.
+
+
+
+5.5. Target-Specific Optimization of Primitive Functions
+
+
+Header file primitives.h
(in directory
+source/include
) declares macros and functions for numerous
+underlying arithmetic operations upon which many of SoftFloat’s
+floating-point functions are ultimately built.
+The SoftFloat sources include implementations of all of these functions/macros,
+written as standard C code, so a complete and correct SoftFloat library can be
+created using only the supplied code for all functions.
+However, for many targets, SoftFloat’s performance can be improved by
+substituting target-specific implementations of some of the functions/macros
+declared in primitives.h
.
+
+
+
+For example, primitives.h
declares a function called
+softfloat_countLeadingZeros32
that takes an unsigned
+32-bit integer as an argument and returns the number of the
+integer’s most-significant bits that are zeros.
+While the SoftFloat sources include an implementation of this function written
+in standard C, many processors can perform this same function
+directly in only one or two machine instructions.
+An alternative, target-specific implementation that maps to those instructions
+is likely to be more efficient than the generic C code from the SoftFloat
+package.
+
+
+
+A build target can replace the supplied version of any function or macro of
+primitives.h
by defining a macro with the same name in the
+target’s platform.h
header file.
+For this purpose, it may be helpful for platform.h
to
+#include
header file primitiveTypes.h
, which defines
+types used for arguments and results of functions declared in
+primitives.h
.
+When a desired replacement implementation is a function, not a macro, it is
+sufficient for platform.h
to include the line
+
+
+#define <function-name> <function-name>
+
+
+where <function-name>
is the name of the
+function.
+This technically defines <function-name>
+as a macro, but one that resolves to the same name, which may then be a
+function.
+(A preprocessor that conforms to the C Standard is required to limit recursive
+macro expansion from being applied more than once.)
+
+
+
+The supplied header file opts-GCC.h
(in directory
+source/include
) provides an example of target-specific
+optimization for the GCC compiler.
+Each GCC target example in the build
directory has
+
+#include "opts-GCC.h"
+
+in its platform.h
header file.
+Before opts-GCC.h
is included, the following macros must be
+defined (or not) to control which features are invoked:
+
+
+SOFTFLOAT_BUILTIN_CLZ
+-
+If defined, SoftFloat’s internal
+‘
countLeadingZeros
’ functions use intrinsics
+__builtin_clz
and __builtin_clzll
.
+
+SOFTFLOAT_INTRINSIC_INT128
+-
+If defined, SoftFloat makes use of GCC’s nonstandard 128-bit
+integer type
__int128
.
+
+
+
+On some machines, these improvements are observed to increase the speeds of
+f64_mul
and f128_mul
by around 20 to 25%, although
+other functions receive less dramatic boosts, or none at all.
+Results can vary greatly across different platforms.
+
+
+
+6. Testing SoftFloat
+
+
+SoftFloat can be tested using the testsoftfloat
program by the
+same author.
+This program is part of the Berkeley TestFloat package available at the Web
+page
+http://www.jhauser.us/arithmetic/TestFloat.html
.
+The TestFloat package also has a program called timesoftfloat
that
+measures the speed of SoftFloat’s floating-point functions.
+
+
+
+7. Providing SoftFloat as a Common Library for Applications
+
+
+Header file softfloat.h
defines the SoftFloat interface as seen by
+clients.
+If the SoftFloat library will be made a common library for programs on a
+system, the supplied softfloat.h
has a couple of deficiencies for
+this purpose:
+
+-
+As supplied,
softfloat.h
depends on another header,
+softfloat_types.h
, that is not intended for public use but which
+must also be visible to the programmer’s compiler.
+ -
+More troubling, at the time
softfloat.h
is included in a C source
+file, macros SOFTFLOAT_FAST_INT64
and THREAD_LOCAL
+must be defined, or not defined, consistent with how these macro were defined
+when the SoftFloat library was built.
+
+In the situation that new programs may regularly #include
header
+file softfloat.h
, it is recommended that a custom, self-contained
+version of this header file be created that eliminates these issues.
+
+
+
+8. Contact Information
+
+
+At the time of this writing, the most up-to-date information about SoftFloat
+and the latest release can be found at the Web page
+http://www.jhauser.us/arithmetic/SoftFloat.html
.
+
+
+
+
+
diff --git a/src/cpu/softfloat3e/doc/SoftFloat.html b/src/cpu/softfloat3e/doc/SoftFloat.html
new file mode 100644
index 0000000000..b72b407f4f
--- /dev/null
+++ b/src/cpu/softfloat3e/doc/SoftFloat.html
@@ -0,0 +1,1527 @@
+
+
+
+
+Berkeley SoftFloat Library Interface
+
+
+
+
+Berkeley SoftFloat Release 3e: Library Interface
+
+
+John R. Hauser
+2018 January 20
+
+
+
+Contents
+
+
+
+
+
+1. Introduction |
+2. Limitations |
+3. Acknowledgments and License |
+4. Types and Functions |
+ | 4.1. Boolean and Integer Types |
+ | 4.2. Floating-Point Types |
+ | 4.3. Supported Floating-Point Functions |
+
+ |
+ 4.4. Non-canonical Representations in extFloat80_t |
+
+ | 4.5. Conventions for Passing Arguments and Results |
+5. Reserved Names |
+6. Mode Variables |
+ | 6.1. Rounding Mode |
+ | 6.2. Underflow Detection |
+
+ |
+ 6.3. Rounding Precision for the 80-Bit Extended Format |
+
+7. Exceptions and Exception Flags |
+8. Function Details |
+ | 8.1. Conversions from Integer to Floating-Point |
+ | 8.2. Conversions from Floating-Point to Integer |
+ | 8.3. Conversions Among Floating-Point Types |
+ | 8.4. Basic Arithmetic Functions |
+ | 8.5. Fused Multiply-Add Functions |
+ | 8.6. Remainder Functions |
+ | 8.7. Round-to-Integer Functions |
+ | 8.8. Comparison Functions |
+ | 8.9. Signaling NaN Test Functions |
+ | 8.10. Raise-Exception Function |
+9. Changes from SoftFloat Release 2 |
+ | 9.1. Name Changes |
+ | 9.2. Changes to Function Arguments |
+ | 9.3. Added Capabilities |
+ | 9.4. Better Compatibility with the C Language |
+ | 9.5. New Organization as a Library |
+ | 9.6. Optimization Gains (and Losses) |
+10. Future Directions |
+11. Contact Information |
+
+
+
+
+1. Introduction
+
+
+Berkeley SoftFloat is a software implementation of binary floating-point that
+conforms to the IEEE Standard for Floating-Point Arithmetic.
+The current release supports five binary formats: 16-bit
+half-precision, 32-bit single-precision, 64-bit
+double-precision, 80-bit double-extended-precision, and
+128-bit quadruple-precision.
+The following functions are supported for each format:
+
+-
+addition, subtraction, multiplication, division, and square root;
+
-
+fused multiply-add as defined by the IEEE Standard, except for
+80-bit double-extended-precision;
+
-
+remainder as defined by the IEEE Standard;
+
-
+round to integral value;
+
-
+comparisons;
+
-
+conversions to/from other supported formats; and
+
-
+conversions to/from 32-bit and 64-bit integers,
+signed and unsigned.
+
+All operations required by the original 1985 version of the IEEE Floating-Point
+Standard are implemented, except for conversions to and from decimal.
+
+
+
+This document gives information about the types defined and the routines
+implemented by SoftFloat.
+It does not attempt to define or explain the IEEE Floating-Point Standard.
+Information about the standard is available elsewhere.
+
+
+
+The current version of SoftFloat is Release 3e.
+This release modifies the behavior of the rarely used odd rounding mode
+(round to odd, also known as jamming), and also adds some new
+specialization and optimization examples for those compiling SoftFloat.
+
+
+
+The previous Release 3d fixed bugs that were found in the square
+root functions for the 64-bit, 80-bit, and
+128-bit floating-point formats.
+(Thanks to Alexei Sibidanov at the University of Victoria for reporting an
+incorrect result.)
+The bugs affected all prior Release-3 versions of SoftFloat
+through 3c.
+The flaw in the 64-bit floating-point square root function was of
+very minor impact, causing a 1-ulp error (1 unit in
+the last place) a few times out of a billion.
+The bugs in the 80-bit and 128-bit square root
+functions were more serious.
+Although incorrect results again occurred only a few times out of a billion,
+when they did occur a large portion of the less-significant bits could be
+wrong.
+
+
+
+Among earlier releases, 3b was notable for adding support for the
+16-bit half-precision format.
+For more about the evolution of SoftFloat releases, see
+SoftFloat-history.html
.
+
+
+
+The functional interface of SoftFloat Release 3 and later differs
+in many details from the releases that came before.
+For specifics of these differences, see section 9 below,
+Changes from SoftFloat Release 2.
+
+
+
+2. Limitations
+
+
+SoftFloat assumes the computer has an addressable byte size of 8 or
+16 bits.
+(Nearly all computers in use today have 8-bit bytes.)
+
+
+
+SoftFloat is written in C and is designed to work with other C code.
+The C compiler used must conform at a minimum to the 1989 ANSI standard for the
+C language (same as the 1990 ISO standard) and must in addition support basic
+arithmetic on 64-bit integers.
+Earlier releases of SoftFloat included implementations of 32-bit
+single-precision and 64-bit double-precision floating-point that
+did not require 64-bit integers, but this option is not supported
+starting with Release 3.
+Since 1999, ISO standards for C have mandated compiler support for
+64-bit integers.
+A compiler conforming to the 1999 C Standard or later is recommended but not
+strictly required.
+
+
+
+Most operations not required by the original 1985 version of the IEEE
+Floating-Point Standard but added in the 2008 version are not yet supported in
+SoftFloat Release 3e.
+
+
+
+3. Acknowledgments and License
+
+
+The SoftFloat package was written by me, John R. Hauser.
+Release 3 of SoftFloat was a completely new implementation
+supplanting earlier releases.
+The project to create Release 3 (now through 3e) was
+done in the employ of the University of California, Berkeley, within the
+Department of Electrical Engineering and Computer Sciences, first for the
+Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab.
+The work was officially overseen by Prof. Krste Asanovic, with funding provided
+by these sources:
+
+
+
+
+
+
+Par Lab: |
+ |
+
+Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery
+(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia,
+NVIDIA, Oracle, and Samsung.
+ |
+
+
+ASPIRE Lab: |
+ |
+
+DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from
+ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA,
+Oracle, and Samsung.
+ |
+
+
+
+
+
+
+The following applies to the whole of SoftFloat Release 3e as well
+as to each source file individually.
+
+
+
+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 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:
+
+
+-
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions, and the following disclaimer.
+
+
+ -
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions, and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+
+ -
+
+Neither the name of the University 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.
+
+
+
+4. Types and Functions
+
+
+The types and functions of SoftFloat are declared in header file
+softfloat.h
.
+
+
+4.1. Boolean and Integer Types
+
+
+Header file softfloat.h
depends on standard headers
+<stdbool.h>
and <stdint.h>
to define type
+bool
and several integer types.
+These standard headers have been part of the ISO C Standard Library since 1999.
+With any recent compiler, they are likely to be supported, even if the compiler
+does not claim complete conformance to the latest ISO C Standard.
+For older or nonstandard compilers, a port of SoftFloat may have substitutes
+for these headers.
+Header softfloat.h
depends only on the name bool
from
+<stdbool.h>
and on these type names from
+<stdint.h>
:
+
+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+uint_fast8_t
+uint_fast32_t
+uint_fast64_t
+int_fast32_t
+int_fast64_t
+
+
+
+
+
+4.2. Floating-Point Types
+
+
+The softfloat.h
header defines five floating-point types:
+
+
+
+float16_t |
+16-bit half-precision binary format |
+
+
+float32_t |
+32-bit single-precision binary format |
+
+
+float64_t |
+64-bit double-precision binary format |
+
+
+extFloat80_t |
+80-bit double-extended-precision binary format (old Intel or
+Motorola format) |
+
+
+float128_t |
+128-bit quadruple-precision binary format |
+
+
+
+The non-extended types are each exactly the size specified:
+16 bits for float16_t
, 32 bits for
+float32_t
, 64 bits for float64_t
, and
+128 bits for float128_t
.
+Aside from these size requirements, the definitions of all these types may
+differ for different ports of SoftFloat to specific systems.
+A given port of SoftFloat may or may not define some of the floating-point
+types as aliases for the C standard types float
,
+double
, and long
double
.
+
+
+
+Header file softfloat.h
also defines a structure,
+struct
extFloat80M
, for the representation of
+80-bit double-extended-precision floating-point values in memory.
+This structure is the same size as type extFloat80_t
and contains
+at least these two fields (not necessarily in this order):
+
+
+uint16_t signExp;
+uint64_t signif;
+
+
+Field signExp
contains the sign and exponent of the floating-point
+value, with the sign in the most significant bit (bit 15) and the
+encoded exponent in the other 15 bits.
+Field signif
is the complete 64-bit significand of
+the floating-point value.
+(In the usual encoding for 80-bit extended floating-point, the
+leading 1 bit of normalized numbers is not implicit but is stored
+in the most significant bit of the significand.)
+
+
+4.3. Supported Floating-Point Functions
+
+
+SoftFloat implements these arithmetic operations for its floating-point types:
+
+-
+conversions between any two floating-point formats;
+
-
+for each floating-point format, conversions to and from signed and unsigned
+32-bit and 64-bit integers;
+
-
+for each format, the usual addition, subtraction, multiplication, division, and
+square root operations;
+
-
+for each format except
extFloat80_t
, the fused multiply-add
+operation defined by the IEEE Standard;
+ -
+for each format, the floating-point remainder operation defined by the IEEE
+Standard;
+
-
+for each format, a “round to integer” operation that rounds to the
+nearest integer value in the same format; and
+
-
+comparisons between two values in the same floating-point format.
+
+
+
+
+The following operations required by the 2008 IEEE Floating-Point Standard are
+not supported in SoftFloat Release 3e:
+
+-
+nextUp, nextDown, minNum, maxNum, minNumMag,
+maxNumMag, scaleB, and logB;
+
-
+conversions between floating-point formats and decimal or hexadecimal character
+sequences;
+
-
+all “quiet-computation” operations (copy, negate,
+abs, and copySign, which all involve only simple copying and/or
+manipulation of the floating-point sign bit); and
+
-
+all “non-computational” operations other than isSignaling
+(which is supported).
+
+
+
+4.4. Non-canonical Representations in extFloat80_t
+
+
+Because the 80-bit double-extended-precision format,
+extFloat80_t
, stores an explicit leading significand bit, many
+finite floating-point numbers are encodable in this type in multiple equivalent
+forms.
+Of these multiple encodings, there is always a unique one with the least
+encoded exponent value, and this encoding is considered the canonical
+representation of the floating-point number.
+Any other equivalent representations (having a higher encoded exponent value)
+are non-canonical.
+For a value in the subnormal range (including zero), the canonical
+representation always has an encoded exponent of zero and a leading significand
+bit of 0.
+For finite values outside the subnormal range, the canonical representation
+always has an encoded exponent that is nonzero and a leading significand bit
+of 1.
+
+
+
+For an infinity or NaN, the leading significand bit is similarly expected to
+be 1.
+An infinity or NaN with a leading significand bit of 0 is again
+considered non-canonical.
+Hence, altogether, to be canonical, a value of type extFloat80_t
+must have a leading significand bit of 1, unless the value is
+subnormal or zero, in which case the leading significand bit and the encoded
+exponent must both be zero.
+
+
+
+SoftFloat’s functions are not guaranteed to operate as expected when
+inputs of type extFloat80_t
are non-canonical.
+Assuming all of a function’s extFloat80_t
inputs (if any)
+are canonical, function outputs of type extFloat80_t
will always
+be canonical.
+
+
+4.5. Conventions for Passing Arguments and Results
+
+
+Values that are at most 64 bits in size (i.e., not the
+80-bit or 128-bit floating-point formats) are in all
+cases passed as function arguments by value.
+Likewise, when an output of a function is no more than 64 bits, it
+is always returned directly as the function result.
+Thus, for example, the SoftFloat function for adding two 64-bit
+floating-point values has this simple signature:
+
+float64_t f64_add( float64_t, float64_t );
+
+
+
+
+The story is more complex when function inputs and outputs are
+80-bit and 128-bit floating-point.
+For these types, SoftFloat always provides a function that passes these larger
+values into or out of the function indirectly, via pointers.
+For example, for adding two 128-bit floating-point values,
+SoftFloat supplies this function:
+
+void f128M_add( const float128_t *, const float128_t *, float128_t * );
+
+The first two arguments point to the values to be added, and the last argument
+points to the location where the sum will be stored.
+The M
in the name f128M_add
is mnemonic for the fact
+that the 128-bit inputs and outputs are “in memory”,
+pointed to by pointer arguments.
+
+
+
+All ports of SoftFloat implement these pass-by-pointer functions for
+types extFloat80_t
and float128_t
.
+At the same time, SoftFloat ports may also implement alternate versions of
+these same functions that pass extFloat80_t
and
+float128_t
by value, like the smaller formats.
+Thus, besides the function with name f128M_add
shown above, a
+SoftFloat port may also supply an equivalent function with this signature:
+
+float128_t f128_add( float128_t, float128_t );
+
+
+
+
+As a general rule, on computers where the machine word size is
+32 bits or smaller, only the pass-by-pointer versions of functions
+(e.g., f128M_add
) are provided for types extFloat80_t
+and float128_t
, because passing such large types directly can have
+significant extra cost.
+On computers where the word size is 64 bits or larger, both
+function versions (f128M_add
and f128_add
) are
+provided, because the cost of passing by value is then more reasonable.
+Applications that must be portable accross both classes of computers must use
+the pointer-based functions, as these are always implemented.
+However, if it is known that SoftFloat includes the by-value functions for all
+platforms of interest, programmers can use whichever version they prefer.
+
+
+
+5. Reserved Names
+
+
+In addition to the variables and functions documented here, SoftFloat defines
+some symbol names for its own private use.
+These private names always begin with the prefix
+‘softfloat_
’.
+When a program includes header softfloat.h
or links with the
+SoftFloat library, all names with prefix ‘softfloat_
’
+are reserved for possible use by SoftFloat.
+Applications that use SoftFloat should not define their own names with this
+prefix, and should reference only such names as are documented.
+
+
+
+6. Mode Variables
+
+
+The following global variables control rounding mode, underflow detection, and
+the 80-bit extended format’s rounding precision:
+
+softfloat_roundingMode
+softfloat_detectTininess
+extF80_roundingPrecision
+
+These mode variables are covered in the next several subsections.
+For some SoftFloat ports, these variables may be per-thread (declared
+thread_local
), meaning that different execution threads have their
+own separate copies of the variables.
+
+
+6.1. Rounding Mode
+
+
+All five rounding modes defined by the 2008 IEEE Floating-Point Standard are
+implemented for all operations that require rounding.
+Some ports of SoftFloat may also implement the round-to-odd mode.
+
+
+
+The rounding mode is selected by the global variable
+
+uint_fast8_t softfloat_roundingMode;
+
+This variable may be set to one of the values
+
+
+
+softfloat_round_near_even |
+round to nearest, with ties to even |
+
+
+softfloat_round_near_maxMag |
+round to nearest, with ties to maximum magnitude (away from zero) |
+
+
+softfloat_round_minMag |
+round to minimum magnitude (toward zero) |
+
+
+softfloat_round_min |
+round to minimum (down) |
+
+
+softfloat_round_max |
+round to maximum (up) |
+
+
+softfloat_round_odd |
+round to odd (jamming), if supported by the SoftFloat port |
+
+
+
+Variable softfloat_roundingMode
is initialized to
+softfloat_round_near_even
.
+
+
+
+When softfloat_round_odd
is the rounding mode for a function that
+rounds to an integer value (either conversion to an integer format or a
+‘roundToInt
’ function), if the input is not already an
+integer, the rounded result is the closest odd integer.
+For other operations, this rounding mode acts as though the floating-point
+result is first rounded to minimum magnitude, the same as
+softfloat_round_minMag
, and then, if the result is inexact, the
+least-significant bit of the result is set to 1.
+Rounding to odd is also known as jamming.
+
+
+6.2. Underflow Detection
+
+
+In the terminology of the IEEE Standard, SoftFloat can detect tininess for
+underflow either before or after rounding.
+The choice is made by the global variable
+
+uint_fast8_t softfloat_detectTininess;
+
+which can be set to either
+
+softfloat_tininess_beforeRounding
+softfloat_tininess_afterRounding
+
+Detecting tininess after rounding is usually better because it results in fewer
+spurious underflow signals.
+The other option is provided for compatibility with some systems.
+Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat
+always detects loss of accuracy for underflow as an inexact result.
+
+
+6.3. Rounding Precision for the 80-Bit Extended Format
+
+
+For extFloat80_t
only, the rounding precision of the basic
+arithmetic operations is controlled by the global variable
+
+uint_fast8_t extF80_roundingPrecision;
+
+The operations affected are:
+
+extF80_add
+extF80_sub
+extF80_mul
+extF80_div
+extF80_sqrt
+
+When extF80_roundingPrecision
is set to its default value of 80,
+these operations are rounded to the full precision of the 80-bit
+double-extended-precision format, like occurs for other formats.
+Setting extF80_roundingPrecision
to 32 or to 64 causes the
+operations listed to be rounded to 32-bit precision (equivalent to
+float32_t
) or to 64-bit precision (equivalent to
+float64_t
), respectively.
+When rounding to reduced precision, additional bits in the result significand
+beyond the rounding point are set to zero.
+The consequences of setting extF80_roundingPrecision
to a value
+other than 32, 64, or 80 is not specified.
+Operations other than the ones listed above are not affected by
+extF80_roundingPrecision
.
+
+
+
+7. Exceptions and Exception Flags
+
+
+All five exception flags required by the IEEE Floating-Point Standard are
+implemented.
+Each flag is stored as a separate bit in the global variable
+
+uint_fast8_t softfloat_exceptionFlags;
+
+The positions of the exception flag bits within this variable are determined by
+the bit masks
+
+softfloat_flag_inexact
+softfloat_flag_underflow
+softfloat_flag_overflow
+softfloat_flag_infinite
+softfloat_flag_invalid
+
+Variable softfloat_exceptionFlags
is initialized to all zeros,
+meaning no exceptions.
+
+
+
+For some SoftFloat ports, softfloat_exceptionFlags
may be
+per-thread (declared thread_local
), meaning that different
+execution threads have their own separate instances of it.
+
+
+
+An individual exception flag can be cleared with the statement
+
+softfloat_exceptionFlags &= ~softfloat_flag_<exception>;
+
+where <exception>
is the appropriate name.
+To raise a floating-point exception, function softfloat_raiseFlags
+should normally be used.
+
+
+
+When SoftFloat detects an exception other than inexact, it calls
+softfloat_raiseFlags
.
+The default version of this function simply raises the corresponding exception
+flags.
+Particular ports of SoftFloat may support alternate behavior, such as exception
+traps, by modifying the default softfloat_raiseFlags
.
+A program may also supply its own softfloat_raiseFlags
function to
+override the one from the SoftFloat library.
+
+
+
+Because inexact results occur frequently under most circumstances (and thus are
+hardly exceptional), SoftFloat does not ordinarily call
+softfloat_raiseFlags
for inexact exceptions.
+It does always raise the inexact exception flag as required.
+
+
+
+8. Function Details
+
+
+In this section, <float>
appears in function names as
+a substitute for one of these abbreviations:
+
+
+
+f16 |
+indicates float16_t , passed by value |
+
+
+f32 |
+indicates float32_t , passed by value |
+
+
+f64 |
+indicates float64_t , passed by value |
+
+
+extF80M |
+indicates extFloat80_t , passed indirectly via pointers |
+
+
+extF80 |
+indicates extFloat80_t , passed by value |
+
+
+f128M |
+indicates float128_t , passed indirectly via pointers |
+
+
+f128 |
+indicates float128_t , passed by value |
+
+
+
+The circumstances under which values of floating-point types
+extFloat80_t
and float128_t
may be passed either by
+value or indirectly via pointers was discussed earlier in
+section 4.5, Conventions for Passing Arguments and Results.
+
+
+8.1. Conversions from Integer to Floating-Point
+
+
+All conversions from a 32-bit or 64-bit integer,
+signed or unsigned, to a floating-point format are supported.
+Functions performing these conversions have these names:
+
+ui32_to_<float>
+ui64_to_<float>
+i32_to_<float>
+i64_to_<float>
+
+Conversions from 32-bit integers to 64-bit
+double-precision and larger formats are always exact, and likewise conversions
+from 64-bit integers to 80-bit
+double-extended-precision and 128-bit quadruple-precision are also
+always exact.
+
+
+
+Each conversion function takes one input of the appropriate type and generates
+one output.
+The following illustrates the signatures of these functions in cases when the
+floating-point result is passed either by value or via pointers:
+
+
+float64_t i32_to_f64( int32_t a );
+
+
+void i32_to_f128M( int32_t a, float128_t *destPtr );
+
+
+
+
+8.2. Conversions from Floating-Point to Integer
+
+
+Conversions from a floating-point format to a 32-bit or
+64-bit integer, signed or unsigned, are supported with these
+functions:
+
+<float>_to_ui32
+<float>_to_ui64
+<float>_to_i32
+<float>_to_i64
+
+The functions have signatures as follows, depending on whether the
+floating-point input is passed by value or via pointers:
+
+
+int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+int_fast32_t
+ f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact );
+
+
+
+
+
+The roundingMode
argument specifies the rounding mode for
+the conversion.
+The variable that usually indicates rounding mode,
+softfloat_roundingMode
, is ignored.
+Argument exact
determines whether the inexact
+exception flag is raised if the conversion is not exact.
+If exact
is true
, the inexact flag may
+be raised;
+otherwise, it will not be, even if the conversion is inexact.
+
+
+
+A conversion from floating-point to integer format raises the invalid
+exception if the source value cannot be rounded to a representable integer of
+the desired size (32 or 64 bits).
+In such circumstances, the integer result returned is determined by the
+particular port of SoftFloat, although typically this value will be either the
+maximum or minimum value of the integer format.
+The functions that convert to integer types never raise the floating-point
+overflow exception.
+
+
+
+Because languages such as C require that conversions to integers
+be rounded toward zero, the following functions are provided for improved speed
+and convenience:
+
+<float>_to_ui32_r_minMag
+<float>_to_ui64_r_minMag
+<float>_to_i32_r_minMag
+<float>_to_i64_r_minMag
+
+These functions round only toward zero (to minimum magnitude).
+The signatures for these functions are the same as above without the redundant
+roundingMode
argument:
+
+
+int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact );
+
+
+int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact );
+
+
+
+
+8.3. Conversions Among Floating-Point Types
+
+
+Conversions between floating-point formats are done by functions with these
+names:
+
+<float>_to_<float>
+
+All combinations of source and result type are supported where the source and
+result are different formats.
+There are four different styles of signature for these functions, depending on
+whether the input and the output floating-point values are passed by value or
+via pointers:
+
+
+float32_t f64_to_f32( float64_t a );
+
+
+float32_t f128M_to_f32( const float128_t *aPtr );
+
+
+void f32_to_f128M( float32_t a, float128_t *destPtr );
+
+
+void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *destPtr );
+
+
+
+
+
+Conversions from a smaller to a larger floating-point format are always exact
+and so require no rounding.
+
+
+8.4. Basic Arithmetic Functions
+
+
+The following basic arithmetic functions are provided:
+
+<float>_add
+<float>_sub
+<float>_mul
+<float>_div
+<float>_sqrt
+
+Each floating-point operation takes two operands, except for sqrt
+(square root) which takes only one.
+The operands and result are all of the same floating-point format.
+Signatures for these functions take the following forms:
+
+
+float64_t f64_add( float64_t a, float64_t b );
+
+
+void
+ f128M_add(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+float64_t f64_sqrt( float64_t a );
+
+
+void f128M_sqrt( const float128_t *aPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments
+aPtr
and bPtr
point to the input
+operands, and the last argument, destPtr
, points to the
+location where the result is stored.
+
+
+
+Rounding of the 80-bit double-extended-precision
+(extFloat80_t
) functions is affected by variable
+extF80_roundingPrecision
, as explained earlier in
+section 6.3,
+Rounding Precision for the 80-Bit Extended Format.
+
+
+8.5. Fused Multiply-Add Functions
+
+
+The 2008 version of the IEEE Floating-Point Standard defines a fused
+multiply-add operation that does a combined multiplication and addition
+with only a single rounding.
+SoftFloat implements fused multiply-add with functions
+
+<float>_mulAdd
+
+Unlike other operations, fused multiple-add is not supported for the
+80-bit double-extended-precision format,
+extFloat80_t
.
+
+
+
+Depending on whether floating-point values are passed by value or via pointers,
+the fused multiply-add functions have signatures of these forms:
+
+
+float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c );
+
+
+void
+ f128M_mulAdd(
+ const float128_t *aPtr,
+ const float128_t *bPtr,
+ const float128_t *cPtr,
+ float128_t *destPtr
+ );
+
+
+The functions compute
+(a
× b
)
+ + c
+with a single rounding.
+When floating-point values are passed indirectly through pointers, arguments
+aPtr
, bPtr
, and
+cPtr
point to operands a
,
+b
, and c
respectively, and
+destPtr
points to the location where the result is stored.
+
+
+
+If one of the multiplication operands a
and
+b
is infinite and the other is zero, these functions raise
+the invalid exception even if operand c
is a quiet NaN.
+
+
+8.6. Remainder Functions
+
+
+For each format, SoftFloat implements the remainder operation defined by the
+IEEE Floating-Point Standard.
+The remainder functions have names
+
+<float>_rem
+
+Each remainder operation takes two floating-point operands of the same format
+and returns a result in the same format.
+Depending on whether floating-point values are passed by value or via pointers,
+the remainder functions have signatures of these forms:
+
+
+float64_t f64_rem( float64_t a, float64_t b );
+
+
+void
+ f128M_rem(
+ const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments
+aPtr
and bPtr
point to operands
+a
and b
respectively, and
+destPtr
points to the location where the result is stored.
+
+
+
+The IEEE Standard remainder operation computes the value
+a
+ − n × b
,
+where n is the integer closest to
+a
÷ b
.
+If a
÷ b
is exactly
+halfway between two integers, n is the even integer closest to
+a
÷ b
.
+The IEEE Standard’s remainder operation is always exact and so requires
+no rounding.
+
+
+
+Depending on the relative magnitudes of the operands, the remainder
+functions can take considerably longer to execute than the other SoftFloat
+functions.
+This is an inherent characteristic of the remainder operation itself and is not
+a flaw in the SoftFloat implementation.
+
+
+8.7. Round-to-Integer Functions
+
+
+For each format, SoftFloat implements the round-to-integer operation specified
+by the IEEE Floating-Point Standard.
+These functions are named
+
+<float>_roundToInt
+
+Each round-to-integer operation takes a single floating-point operand.
+This operand is rounded to an integer according to a specified rounding mode,
+and the resulting integer value is returned in the same floating-point format.
+(Note that the result is not an integer type.)
+
+
+
+The signatures of the round-to-integer functions are similar to those for
+conversions to an integer type:
+
+
+float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+void
+ f128M_roundToInt(
+ const float128_t *aPtr,
+ uint_fast8_t roundingMode,
+ bool exact,
+ float128_t *destPtr
+ );
+
+
+When floating-point values are passed indirectly through pointers,
+aPtr
points to the input operand and
+destPtr
points to the location where the result is stored.
+
+
+
+The roundingMode
argument specifies the rounding mode to
+apply.
+The variable that usually indicates rounding mode,
+softfloat_roundingMode
, is ignored.
+Argument exact
determines whether the inexact
+exception flag is raised if the conversion is not exact.
+If exact
is true
, the inexact flag may
+be raised;
+otherwise, it will not be, even if the conversion is inexact.
+
+
+8.8. Comparison Functions
+
+
+For each format, the following floating-point comparison functions are
+provided:
+
+<float>_eq
+<float>_le
+<float>_lt
+
+Each comparison takes two operands of the same type and returns a Boolean.
+The abbreviation eq
stands for “equal” (=);
+le
stands for “less than or equal” (≤);
+and lt
stands for “less than” (<).
+Depending on whether the floating-point operands are passed by value or via
+pointers, the comparison functions have signatures of these forms:
+
+
+bool f64_eq( float64_t a, float64_t b );
+
+
+bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr );
+
+
+
+
+
+The usual greater-than (>), greater-than-or-equal (≥), and not-equal
+(≠) comparisons are easily obtained from the functions provided.
+The not-equal function is just the logical complement of the equal function.
+The greater-than-or-equal function is identical to the less-than-or-equal
+function with the arguments in reverse order, and likewise the greater-than
+function is identical to the less-than function with the arguments reversed.
+
+
+
+The IEEE Floating-Point Standard specifies that the less-than-or-equal and
+less-than comparisons by default raise the invalid exception if either
+operand is any kind of NaN.
+Equality comparisons, on the other hand, are defined by default to raise the
+invalid exception only for signaling NaNs, not quiet NaNs.
+For completeness, SoftFloat provides these complementary functions:
+
+<float>_eq_signaling
+<float>_le_quiet
+<float>_lt_quiet
+
+The signaling
equality comparisons are identical to the default
+equality comparisons except that the invalid exception is raised for any
+NaN input, not just for signaling NaNs.
+Similarly, the quiet
comparison functions are identical to their
+default counterparts except that the invalid exception is not raised for
+quiet NaNs.
+
+
+8.9. Signaling NaN Test Functions
+
+
+Functions for testing whether a floating-point value is a signaling NaN are
+provided with these names:
+
+<float>_isSignalingNaN
+
+The functions take one floating-point operand and return a Boolean indicating
+whether the operand is a signaling NaN.
+Accordingly, the functions have the forms
+
+
+bool f64_isSignalingNaN( float64_t a );
+
+
+bool f128M_isSignalingNaN( const float128_t *aPtr );
+
+
+
+
+8.10. Raise-Exception Function
+
+
+SoftFloat provides a single function for raising floating-point exceptions:
+
+
+void softfloat_raiseFlags( uint_fast8_t exceptions );
+
+
+The exceptions
argument is a mask indicating the set of
+exceptions to raise.
+(See earlier section 7, Exceptions and Exception Flags.)
+In addition to setting the specified exception flags in variable
+softfloat_exceptionFlags
, the softfloat_raiseFlags
+function may cause a trap or abort appropriate for the current system.
+
+
+
+9. Changes from SoftFloat Release 2
+
+
+Apart from a change in the legal use license, Release 3 of
+SoftFloat introduced numerous technical differences compared to earlier
+releases.
+
+
+9.1. Name Changes
+
+
+The most obvious and pervasive difference compared to Release 2
+is that the names of most functions and variables have changed, even when the
+behavior has not.
+First, the floating-point types, the mode variables, the exception flags
+variable, the function to raise exceptions, and various associated constants
+have been renamed as follows:
+
+
+
+old name, Release 2: |
+new name, Release 3: |
+
+
+float32 |
+float32_t |
+
+
+float64 |
+float64_t |
+
+
+floatx80 |
+extFloat80_t |
+
+
+float128 |
+float128_t |
+
+
+float_rounding_mode |
+softfloat_roundingMode |
+
+
+float_round_nearest_even |
+softfloat_round_near_even |
+
+
+float_round_to_zero |
+softfloat_round_minMag |
+
+
+float_round_down |
+softfloat_round_min |
+
+
+float_round_up |
+softfloat_round_max |
+
+
+float_detect_tininess |
+softfloat_detectTininess |
+
+
+float_tininess_before_rounding |
+softfloat_tininess_beforeRounding |
+
+
+float_tininess_after_rounding |
+softfloat_tininess_afterRounding |
+
+
+floatx80_rounding_precision |
+extF80_roundingPrecision |
+
+
+float_exception_flags |
+softfloat_exceptionFlags |
+
+
+float_flag_inexact |
+softfloat_flag_inexact |
+
+
+float_flag_underflow |
+softfloat_flag_underflow |
+
+
+float_flag_overflow |
+softfloat_flag_overflow |
+
+
+float_flag_divbyzero |
+softfloat_flag_infinite |
+
+
+float_flag_invalid |
+softfloat_flag_invalid |
+
+
+float_raise |
+softfloat_raiseFlags |
+
+
+
+
+
+
+Furthermore, Release 3 adopted the following new abbreviations for
+function names:
+
+
+
+used in names in Release 2: |
+used in names in Release 3: |
+
+ int32 | i32 |
+ int64 | i64 |
+ float32 | f32 |
+ float64 | f64 |
+ floatx80 | extF80 |
+ float128 | f128 |
+
+
+Thus, for example, the function to add two 32-bit floating-point
+numbers, previously called float32_add
in Release 2,
+is now f32_add
.
+Lastly, there have been a few other changes to function names:
+
+
+
+used in names in Release 2: |
+used in names in Release 3: |
+relevant functions: |
+
+
+_round_to_zero |
+_r_minMag |
+conversions from floating-point to integer (section 8.2) |
+
+
+round_to_int |
+roundToInt |
+round-to-integer functions (section 8.7) |
+
+
+is_signaling_nan |
+isSignalingNaN |
+signaling NaN test functions (section 8.9) |
+
+
+
+
+
+9.2. Changes to Function Arguments
+
+
+Besides simple name changes, some operations were given a different interface
+in Release 3 than they had in Release 2:
+
+
+-
+
+Since Release 3, integer arguments and results of functions have
+standard types from header <stdint.h>
, such as
+uint32_t
, whereas previously their types could be defined
+differently for each port of SoftFloat, usually using traditional C types such
+as unsigned
int
.
+Likewise, functions in Release 3 and later pass Booleans as
+standard type bool
from <stdbool.h>
, whereas
+previously these were again passed as a port-specific type (usually
+int
).
+
+
+ -
+
+As explained earlier in section 4.5, Conventions for Passing
+Arguments and Results, SoftFloat functions in Release 3 and
+later may pass 80-bit and 128-bit floating-point
+values through pointers, meaning that functions take pointer arguments and then
+read or write floating-point values at the locations indicated by the pointers.
+In Release 2, floating-point arguments and results were always
+passed by value, regardless of their size.
+
+
+ -
+
+Functions that round to an integer have additional
+roundingMode
and exact
arguments that
+they did not have in Release 2.
+Refer to sections 8.2 and 8.7 for descriptions of these functions
+since Release 3.
+For Release 2, the rounding mode, when needed, was taken from the
+same global variable that affects the basic arithmetic operations (now called
+softfloat_roundingMode
but previously known as
+float_rounding_mode
).
+Also, for Release 2, if the original floating-point input was not
+an exact integer value, and if the invalid exception was not raised by
+the function, the inexact exception was always raised.
+Release 2 had no option to suppress raising inexact in this
+case.
+Applications using SoftFloat Release 3 or later can get the same
+effect as Release 2 by passing variable
+softfloat_roundingMode
for argument
+roundingMode
and true
for argument
+exact
.
+
+
+
+
+
+9.3. Added Capabilities
+
+
+With Release 3, some new features have been added that were not
+present in Release 2:
+
+
+-
+
+A port of SoftFloat can now define any of the floating-point types
+float32_t
, float64_t
, extFloat80_t
, and
+float128_t
as aliases for C’s standard floating-point types
+float
, double
, and long
+double
, using either #define
or typedef
.
+This potential convenience was not supported under Release 2.
+
+
+
+(Note, however, that there may be a performance cost to defining
+SoftFloat’s floating-point types this way, depending on the platform and
+the applications using SoftFloat.
+Ports of SoftFloat may choose to forgo the convenience in favor of better
+speed.)
+
+
+
+
-
+As of Release 3b, 16-bit half-precision,
+
float16_t
, is supported.
+
+
+
+
-
+Functions have been added for converting between the floating-point types and
+unsigned integers.
+Release 2 supported only signed integers, not unsigned.
+
+
+
+
-
+Fused multiply-add functions have been added for all floating-point formats
+except 80-bit double-extended-precision,
+
extFloat80_t
.
+
+
+
+
-
+New rounding modes are supported:
+
softfloat_round_near_maxMag
(round to nearest, with ties to
+maximum magnitude, away from zero), and, as of Release 3c,
+optional softfloat_round_odd
(round to odd, also known as
+jamming).
+
+
+
+
+
+9.4. Better Compatibility with the C Language
+
+
+Release 3 of SoftFloat was written to conform better to the ISO C
+Standard’s rules for portability.
+For example, older releases of SoftFloat employed type conversions in ways
+that, while commonly practiced, are not fully defined by the C Standard.
+Such problematic type conversions have generally been replaced by the use of
+unions, the behavior around which is more strictly regulated these days.
+
+
+9.5. New Organization as a Library
+
+
+Starting with Release 3, SoftFloat now builds as a library.
+Previously, SoftFloat compiled into a single, monolithic object file containing
+all the SoftFloat functions, with the consequence that a program linking with
+SoftFloat would get every SoftFloat function in its binary file even if only a
+few functions were actually used.
+With SoftFloat in the form of a library, a program that is linked by a standard
+linker will include only those functions of SoftFloat that it needs and no
+others.
+
+
+9.6. Optimization Gains (and Losses)
+
+
+Individual SoftFloat functions have been variously improved in
+Release 3 compared to earlier releases.
+In particular, better, faster algorithms have been deployed for the operations
+of division, square root, and remainder.
+For functions operating on the larger 80-bit and
+128-bit formats, extFloat80_t
and
+float128_t
, code size has also generally been reduced.
+
+
+
+However, because Release 2 compiled all of SoftFloat together as a
+single object file, compilers could make optimizations across function calls
+when one SoftFloat function calls another.
+Now that the functions of SoftFloat are compiled separately and only afterward
+linked together into a program, there is not usually the same opportunity to
+optimize across function calls.
+Some loss of speed has been observed due to this change.
+
+
+
+10. Future Directions
+
+
+The following improvements are anticipated for future releases of SoftFloat:
+
+-
+more functions from the 2008 version of the IEEE Floating-Point Standard;
+
-
+consistent, defined behavior for non-canonical representations of extended
+format
extFloat80_t
(discussed in section 4.4,
+Non-canonical Representations in extFloat80_t
).
+
+
+
+
+
+11. Contact Information
+
+
+At the time of this writing, the most up-to-date information about SoftFloat
+and the latest release can be found at the Web page
+http://www.jhauser.us/arithmetic/SoftFloat.html
.
+
+
+
+
+
diff --git a/src/cpu/softfloat3e/extF80_addsub.cc b/src/cpu/softfloat3e/extF80_addsub.cc
new file mode 100644
index 0000000000..a60d2c6be1
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_addsub.cc
@@ -0,0 +1,106 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extern extFloat80_t softfloat_addMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *);
+extern extFloat80_t softfloat_subMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *);
+
+extFloat80_t extF80_add(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ uint16_t uiB64;
+ uint64_t uiB0;
+ bool signB;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ a.signExp = defaultNaNExtF80UI64;
+ a.signif = defaultNaNExtF80UI0;
+ return a;
+ }
+
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ signB = signExtF80UI64(uiB64);
+
+ if (signA == signB) {
+ return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
+ } else {
+ return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
+ }
+}
+
+extFloat80_t extF80_sub(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ uint16_t uiB64;
+ uint64_t uiB0;
+ bool signB;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ a.signExp = defaultNaNExtF80UI64;
+ a.signif = defaultNaNExtF80UI0;
+ return a;
+ }
+
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ signB = signExtF80UI64(uiB64);
+
+ if (signA == signB) {
+ return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
+ } else {
+ return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
+ }
+}
diff --git a/src/cpu/softfloat3e/extF80_class.cc b/src/cpu/softfloat3e/extF80_class.cc
new file mode 100644
index 0000000000..155dc51a2a
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_class.cc
@@ -0,0 +1,71 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "softfloat.h"
+
+softfloat_class_t extF80_class(extFloat80_t a)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+
+ if (! expA) {
+ if (! sigA) return softfloat_zero;
+ return softfloat_denormal; /* denormal or pseudo-denormal */
+ }
+
+ /* valid numbers have the MS bit set */
+ if (!(sigA & UINT64_C(0x8000000000000000)))
+ return softfloat_SNaN; /* report unsupported as SNaNs */
+
+ if (expA == 0x7FFF) {
+ if ((sigA<<1) == 0)
+ return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
+
+ return (sigA & UINT64_C(0x4000000000000000)) ? softfloat_QNaN : softfloat_SNaN;
+ }
+
+ return softfloat_normalized;
+}
diff --git a/src/cpu/softfloat3e/extF80_compare.cc b/src/cpu/softfloat3e/extF80_compare.cc
new file mode 100644
index 0000000000..f8a360a411
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_compare.cc
@@ -0,0 +1,147 @@
+/*============================================================================
+
+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
+#include
+#include <86box/86box.h>
+#include "../cpu.h"
+
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two extended precision floating point numbers. Returns
+| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
+| the value 'a' is less than the corresponding value `b',
+| 'float_relation_greater' if the value 'a' is greater than the corresponding
+| value `b', or 'float_relation_unordered' otherwise.
+*----------------------------------------------------------------------------*/
+
+int extF80_compare(extFloat80_t a, extFloat80_t b, int quiet, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+
+ uint16_t uiB64;
+ uint64_t uiB0;
+ bool signB;
+ int32_t expB;
+ uint64_t sigB;
+
+ struct exp32_sig64 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ softfloat_class_t aClass = extF80_class(a);
+ softfloat_class_t bClass = extF80_class(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (fpu_type < FPU_287XL) {
+ if ((aClass == softfloat_positive_inf) && (bClass == softfloat_negative_inf))
+ {
+ return softfloat_relation_equal;
+ }
+
+ if ((aClass == softfloat_negative_inf) && (bClass == softfloat_positive_inf))
+ {
+ return softfloat_relation_equal;
+ }
+ }
+
+ if (aClass == softfloat_SNaN || bClass == softfloat_SNaN)
+ {
+ /* unsupported reported as SNaN */
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
+ if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (aClass == softfloat_denormal || bClass == softfloat_denormal) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ signB = signExtF80UI64(uiB64);
+ expB = expExtF80UI64(uiB64);
+ sigB = uiB0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (aClass == softfloat_zero) {
+ if (bClass == softfloat_zero) return softfloat_relation_equal;
+ return signB ? softfloat_relation_greater : softfloat_relation_less;
+ }
+
+ if (bClass == softfloat_zero || signA != signB) {
+ return signA ? softfloat_relation_less : softfloat_relation_greater;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (aClass == softfloat_denormal) {
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA += normExpSig.exp + 1;
+ sigA = normExpSig.sig;
+ }
+ if (bClass == softfloat_denormal) {
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB += normExpSig.exp + 1;
+ sigB = normExpSig.sig;
+ }
+
+ if (expA == expB && sigA == sigB)
+ return softfloat_relation_equal;
+
+ int less_than =
+ signA ? ((expB < expA) || ((expB == expA) && (sigB < sigA)))
+ : ((expA < expB) || ((expA == expB) && (sigA < sigB)));
+
+ if (less_than) return softfloat_relation_less;
+ return softfloat_relation_greater;
+}
diff --git a/src/cpu/softfloat3e/extF80_div.cc b/src/cpu/softfloat3e/extF80_div.cc
new file mode 100644
index 0000000000..e4b1fbb24b
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_div.cc
@@ -0,0 +1,188 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t extF80_div(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+ uint16_t uiB64;
+ uint64_t uiB0;
+ bool signB;
+ int32_t expB;
+ uint64_t sigB;
+ bool signZ;
+ struct exp32_sig64 normExpSig;
+ int32_t expZ;
+ struct uint128 rem;
+ uint32_t recip32;
+ uint64_t sigZ;
+ int ix;
+ uint64_t q64;
+ uint32_t q;
+ struct uint128 term;
+ uint64_t sigZExtra;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b))
+ goto invalid;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ signB = signExtF80UI64(uiB64);
+ expB = expExtF80UI64(uiB64);
+ sigB = uiB0;
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
+ if (expB == 0x7FFF) {
+ if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
+ goto invalid;
+ }
+ if (! expB && sigB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000));
+ }
+ if (expB == 0x7FFF) {
+ if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
+ if (! expA && sigA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToExtF80(signZ, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expB) {
+ expB = 1;
+ if (sigB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigB & UINT64_C(0x8000000000000000))) {
+ if (! sigB) {
+ if (! sigA) goto invalid;
+ softfloat_raiseFlags(status, softfloat_flag_infinite);
+ return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000));
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB += normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ if (! expA) {
+ expA = 1;
+ if (sigA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigA & UINT64_C(0x8000000000000000))) {
+ if (! sigA) return packToExtF80(signZ, 0, 0);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA += normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA - expB + 0x3FFF;
+ if (sigA < sigB) {
+ --expZ;
+ rem = softfloat_shortShiftLeft128(0, sigA, 32);
+ } else {
+ rem = softfloat_shortShiftLeft128(0, sigA, 31);
+ }
+ recip32 = softfloat_approxRecip32_1(sigB>>32);
+ sigZ = 0;
+ ix = 2;
+ for (;;) {
+ q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32;
+ q = (q64 + 0x80000000)>>32;
+ --ix;
+ if (ix < 0) break;
+ rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
+ term = softfloat_mul64ByShifted32To128(sigB, 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>>32, sigB<<32);
+ }
+ sigZ = (sigZ<<29) + q;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (((q + 1) & 0x3FFFFF) < 2) {
+ rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
+ term = softfloat_mul64ByShifted32To128(sigB, q);
+ rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
+ term = softfloat_shortShiftLeft128(0, sigB, 32);
+ if (rem.v64 & UINT64_C(0x8000000000000000)) {
+ --q;
+ rem = softfloat_add128(rem.v64, rem.v0, term.v64, term.v0);
+ } else if (softfloat_le128(term.v64, term.v0, rem.v64, rem.v0)) {
+ ++q;
+ rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
+ }
+ if (rem.v64 | rem.v0) q |= 1;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sigZ = (sigZ<<6) + (q>>23);
+ sigZExtra = (uint64_t) ((uint64_t) q<<41);
+ return
+ softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+}
diff --git a/src/cpu/softfloat3e/extF80_extract.cc b/src/cpu/softfloat3e/extF80_extract.cc
new file mode 100644
index 0000000000..692190a47b
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_extract.cc
@@ -0,0 +1,97 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Separate the source extended double-precision floating point value `a'
+| into its exponent and significand, store the significant back to the
+| 'a' and return the exponent. The operation performed is a superset of
+| the IEC/IEEE recommended logb(x) function.
+*----------------------------------------------------------------------------*/
+
+extFloat80_t extF80_extract(extFloat80_t *a, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+ struct exp32_sig64 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(*a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ *a = packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+ return *a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a->signExp;
+ uiA0 = a->signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if (sigA<<1) {
+ *a = softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status);
+ return *a;
+ }
+ return packToExtF80(0, 0x7FFF, BX_CONST64(0x8000000000000000));
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ softfloat_raiseFlags(status, softfloat_flag_divbyzero);
+ *a = packToExtF80(signA, 0, 0);
+ return packToExtF80(1, 0x7FFF, BX_CONST64(0x8000000000000000));
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA = normExpSig.exp + 1;
+ sigA = normExpSig.sig;
+ }
+
+ *a = packToExtF80(signA, 0x3FFF, sigA);
+ return i32_to_extF80(expA - 0x3FFF);
+}
diff --git a/src/cpu/softfloat3e/extF80_mul.cc b/src/cpu/softfloat3e/extF80_mul.cc
new file mode 100644
index 0000000000..d38e97f026
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_mul.cc
@@ -0,0 +1,153 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t extF80_mul(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+ uint16_t uiB64;
+ uint64_t uiB0;
+ bool signB;
+ int32_t expB;
+ uint64_t sigB;
+ bool signZ;
+ uint64_t magBits;
+ struct exp32_sig64 normExpSig;
+ int32_t expZ;
+ struct uint128 sig128Z;
+ uint16_t uiZ64;
+ uint64_t uiZ0;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ signB = signExtF80UI64(uiB64);
+ expB = expExtF80UI64(uiB64);
+ sigB = uiB0;
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) {
+ goto propagateNaN;
+ }
+ magBits = expB | sigB;
+ goto infArg;
+ }
+ if (expB == 0x7FFF) {
+ if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
+ magBits = expA | sigA;
+ goto infArg;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ expA = 1;
+ if (sigA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigA & UINT64_C(0x8000000000000000))) {
+ if (! sigA) {
+ if (! expB && sigB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToExtF80(signZ, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA += normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ expB = 1;
+ if (sigB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigB & UINT64_C(0x8000000000000000))) {
+ if (! sigB) return packToExtF80(signZ, 0, 0);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB += normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA + expB - 0x3FFE;
+ sig128Z = softfloat_mul64To128(sigA, sigB);
+ if (sig128Z.v64 < UINT64_C(0x8000000000000000)) {
+ --expZ;
+ sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0);
+ }
+ return
+ softfloat_roundPackToExtF80(signZ, expZ, sig128Z.v64, sig128Z.v0, softfloat_extF80_roundingPrecision(status), status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infArg:
+ if (! magBits) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ64 = defaultNaNExtF80UI64;
+ uiZ0 = defaultNaNExtF80UI0;
+ } else {
+ if ((! expA && sigA) || (! expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ uiZ64 = packToExtF80UI64(signZ, 0x7FFF);
+ uiZ0 = UINT64_C(0x8000000000000000);
+ }
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+}
diff --git a/src/cpu/softfloat3e/extF80_rem.cc b/src/cpu/softfloat3e/extF80_rem.cc
new file mode 100644
index 0000000000..39d233a7e4
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_rem.cc
@@ -0,0 +1,199 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+ uint16_t uiB64;
+ uint64_t uiB0;
+ int32_t expB;
+ uint64_t sigB;
+ struct exp32_sig64 normExpSig;
+ int32_t expDiff;
+ struct uint128 rem, shiftedSigB;
+ uint32_t q, recip32;
+ uint64_t q64;
+ struct uint128 term, altRem, meanRem;
+ bool signRem;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b))
+ goto invalid;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ expB = expExtF80UI64(uiB64);
+ sigB = uiB0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) {
+ goto propagateNaN;
+ }
+ goto invalid;
+ }
+ if (expB == 0x7FFF) {
+ if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
+ /*--------------------------------------------------------------------
+ | Argument b is an infinity. Doubling `expB' is an easy way to ensure
+ | that `expDiff' later is less than -1, which will result in returning
+ | a canonicalized version of argument a.
+ *--------------------------------------------------------------------*/
+ expB += expB;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expB) {
+ expB = 1;
+ if (sigB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigB & UINT64_C(0x8000000000000000))) {
+ if (! sigB) goto invalid;
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB += normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ if (! expA) {
+ expA = 1;
+ if (sigA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigA & UINT64_C(0x8000000000000000))) {
+ if (! sigA) {
+ expA = 0;
+ goto copyA;
+ }
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA += normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expA - expB;
+ if (expDiff < -1) goto copyA;
+ rem = softfloat_shortShiftLeft128(0, sigA, 32);
+ shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 32);
+ if (expDiff < 1) {
+ if (expDiff) {
+ --expB;
+ shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 33);
+ q = 0;
+ } else {
+ q = (sigB <= sigA);
+ if (q) {
+ rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0);
+ }
+ }
+ } else {
+ recip32 = softfloat_approxRecip32_1(sigB>>32);
+ expDiff -= 30;
+ for (;;) {
+ q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32;
+ if (expDiff < 0) break;
+ q = (q64 + 0x80000000)>>32;
+ rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
+ term = softfloat_mul64ByShifted32To128(sigB, 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, shiftedSigB.v64, shiftedSigB.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_mul64ByShifted32To128(sigB, 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, shiftedSigB.v64, shiftedSigB.v0);
+ goto selectRem;
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ do {
+ altRem = rem;
+ ++q;
+ rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.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_normRoundPackToExtF80(signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ copyA:
+ if (expA < 1) {
+ sigA >>= 1 - expA;
+ expA = 0;
+ }
+ return packToExtF80(signA, expA, sigA);
+}
diff --git a/src/cpu/softfloat3e/extF80_roundToInt.cc b/src/cpu/softfloat3e/extF80_roundToInt.cc
new file mode 100644
index 0000000000..f71cdfc50e
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_roundToInt.cc
@@ -0,0 +1,123 @@
+/*============================================================================
+
+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, 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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t
+ extF80_roundToInt(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64, signUI64;
+ int32_t exp;
+ uint64_t sigA;
+ uint16_t uiZ64;
+ uint64_t sigZ;
+ uint64_t lastBitMask, roundBitsMask;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ signUI64 = uiA64 & packToExtF80UI64(1, 0);
+ exp = expExtF80UI64(uiA64);
+ sigA = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (0x403E <= exp) {
+ if ((exp == 0x7FFF) && (uint64_t) (sigA<<1)) {
+ return softfloat_propagateNaNExtF80UI(uiA64, sigA, 0, 0, status);
+ }
+ return a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp <= 0x3FFE) {
+ if (! exp) {
+ if ((sigA<<1) == 0) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ switch (roundingMode) {
+ case softfloat_round_near_even:
+ if (!(sigA & UINT64_C(0x7FFFFFFFFFFFFFFF))) break;
+ case softfloat_round_near_maxMag:
+ if (exp == 0x3FFE) goto mag1;
+ break;
+ case softfloat_round_min:
+ if (signUI64) goto mag1;
+ break;
+ case softfloat_round_max:
+ if (!signUI64) goto mag1;
+ break;
+ }
+ return packToExtF80(signUI64, 0, 0);
+ mag1:
+ softfloat_setRoundingUp(status);
+ return packToExtF80(signUI64, 0x3FFF, UINT64_C(0x8000000000000000));
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ64 = signUI64 | exp;
+ lastBitMask = (uint64_t) 1<<(0x403E - exp);
+ roundBitsMask = lastBitMask - 1;
+ sigZ = sigA;
+ if (roundingMode == softfloat_round_near_maxMag) {
+ sigZ += lastBitMask>>1;
+ } else if (roundingMode == softfloat_round_near_even) {
+ sigZ += lastBitMask>>1;
+ if (!(sigZ & roundBitsMask)) sigZ &= ~lastBitMask;
+ } else if (roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)) {
+ sigZ += roundBitsMask;
+ }
+ sigZ &= ~roundBitsMask;
+ if (!sigZ) {
+ ++uiZ64;
+ sigZ = UINT64_C(0x8000000000000000);
+ softfloat_setRoundingUp(status);
+ }
+ if (sigZ != sigA) {
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ if (sigZ > sigA)
+ softfloat_setRoundingUp(status);
+ }
+ return packToExtF80_twoargs(uiZ64, sigZ);
+}
diff --git a/src/cpu/softfloat3e/extF80_scale.cc b/src/cpu/softfloat3e/extF80_scale.cc
new file mode 100644
index 0000000000..48bd53afd4
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_scale.cc
@@ -0,0 +1,136 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Scales extended double-precision floating-point value in operand `a' by
+| value `b'. The function truncates the value in the second operand 'b' to
+| an integral value and adds that value to the exponent of the operand 'a'.
+| The operation performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+extFloat80_t extF80_scale(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+ uint16_t uiB64;
+ uint64_t uiB0;
+ bool signB;
+ int32_t expB;
+ uint64_t sigB;
+ struct exp32_sig64 normExpSig;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
+invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ uiB64 = b.signExp;
+ uiB0 = b.signif;
+ signB = signExtF80UI64(uiB64);
+ expB = expExtF80UI64(uiB64);
+ sigB = uiB0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+
+ if (expA == 0x7FFF) {
+ if ((sigA<<1) || ((expB == 0x7FFF) && (sigB<<1))) {
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
+ }
+ if ((expB == 0x7FFF) && signB) goto invalid;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return a;
+ }
+ if (expB == 0x7FFF) {
+ if (sigB<<1) {
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
+ }
+ if ((expA | sigA) == 0) {
+ if (! signB) goto invalid;
+ return a;
+ }
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ if (signB) return packToExtF80(signA, 0, 0);
+ return packToExtF80(signA, 0x7FFF, BX_CONST64(0x8000000000000000));
+ }
+ if (! expA) {
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ if (! sigA) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA = normExpSig.exp + 1;
+ sigA = normExpSig.sig;
+ if (expB < 0x3FFF)
+ return softfloat_normRoundPackToExtF80(signA, expA, sigA, 0, 80, status);
+ }
+ if (!expB) {
+ if (!sigB) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB = normExpSig.exp + 1;
+ sigB = normExpSig.sig;
+ }
+
+ if (expB > 0x400E) {
+ /* generate appropriate overflow/underflow */
+ return softfloat_roundPackToExtF80(signA, signB ? -0x3FFF : 0x7FFF, sigA, 0, 80, status);
+ }
+
+ if (expB < 0x3FFF) return a;
+
+ int shiftCount = 0x403E - expB;
+ sigB >>= shiftCount;
+ int32_t scale = (int32_t) sigB;
+ if (signB) scale = -scale; /* -32768..32767 */
+
+ return softfloat_roundPackToExtF80(signA, expA + scale, sigA, 0, 80, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_sqrt.cc b/src/cpu/softfloat3e/extF80_sqrt.cc
new file mode 100644
index 0000000000..1a5d52e5dc
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_sqrt.cc
@@ -0,0 +1,159 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t extF80_sqrt(extFloat80_t a, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool signA;
+ int32_t expA;
+ uint64_t sigA;
+ struct exp32_sig64 normExpSig;
+ int32_t expZ;
+ uint32_t sig32A, recipSqrt32, sig32Z;
+ struct uint128 rem;
+ uint64_t q, x64, sigZ;
+ struct uint128 y, term;
+ uint64_t sigZExtra;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a))
+ goto invalid;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ signA = signExtF80UI64(uiA64);
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status);
+ }
+ if (! signA) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (signA) {
+ if ((expA | sigA) == 0) return packToExtF80(signA, 0, 0);
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ expA = 1;
+ if (sigA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ if (! (sigA & UINT64_C(0x8000000000000000))) {
+ if (! sigA) return packToExtF80(signA, 0, 0);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ 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) + 0x3FFF;
+ expA &= 1;
+ sig32A = sigA>>32;
+ recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A);
+ sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32;
+ if (expA) {
+ sig32Z >>= 1;
+ rem = softfloat_shortShiftLeft128(0, sigA, 61);
+ } else {
+ rem = softfloat_shortShiftLeft128(0, sigA, 62);
+ }
+ rem.v64 -= (uint64_t) sig32Z * sig32Z;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ q = ((uint32_t) (rem.v64>>2) * (uint64_t) recipSqrt32)>>32;
+ x64 = (uint64_t) sig32Z<<32;
+ sigZ = x64 + (q<<3);
+ y = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
+ /*------------------------------------------------------------------------
+ | (Repeating this loop is a rare occurrence.)
+ *------------------------------------------------------------------------*/
+ for (;;) {
+ term = softfloat_mul64ByShifted32To128(x64 + sigZ, q);
+ rem = softfloat_sub128(y.v64, y.v0, term.v64, term.v0);
+ if (! (rem.v64 & UINT64_C(0x8000000000000000))) break;
+ --q;
+ sigZ -= 1<<3;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
+ x64 = sigZ;
+ sigZ = (sigZ<<1) + (q>>25);
+ sigZExtra = (uint64_t) (q<<39);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((q & 0xFFFFFF) <= 2) {
+ q &= ~(uint64_t) 0xFFFF;
+ sigZExtra = (uint64_t) (q<<39);
+ term = softfloat_mul64ByShifted32To128(x64 + (q>>27), q);
+ x64 = (uint32_t) (q<<5) * (uint64_t) (uint32_t) q;
+ term = softfloat_add128(term.v64, term.v0, 0, x64);
+ rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 28);
+ rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
+ if (rem.v64 & UINT64_C(0x8000000000000000)) {
+ if (! sigZExtra) --sigZ;
+ --sigZExtra;
+ } else {
+ if (rem.v64 | rem.v0) sigZExtra |= 1;
+ }
+ }
+ return
+ softfloat_roundPackToExtF80(0, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_f128.cc b/src/cpu/softfloat3e/extF80_to_f128.cc
new file mode 100644
index 0000000000..24e523cac8
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_f128.cc
@@ -0,0 +1,75 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t extF80_to_f128(extFloat80_t a, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ uint16_t exp;
+ uint64_t frac;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ bool sign;
+ struct uint128 frac128;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ.v64 = defaultNaNF128UI64;
+ uiZ.v0 = defaultNaNF128UI0;
+ return uiZ;
+ }
+
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ exp = expExtF80UI64(uiA64);
+ frac = uiA0 & UINT64_C(0x7FFFFFFFFFFFFFFF);
+ if ((exp == 0x7FFF) && frac) {
+ softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF128UI(&commonNaN);
+ } else {
+ sign = signExtF80UI64(uiA64);
+ frac128 = softfloat_shortShiftLeft128(0, frac, 49);
+ uiZ.v64 = packToF128UI64(sign, exp, frac128.v64);
+ uiZ.v0 = frac128.v0;
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/extF80_to_f16.cc b/src/cpu/softfloat3e/extF80_to_f16.cc
new file mode 100644
index 0000000000..5078e689cc
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_f16.cc
@@ -0,0 +1,89 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 extF80_to_f16(extFloat80_t a, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ struct commonNaN commonNaN;
+ uint16_t uiZ, sig16;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF16UI;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FFF) {
+ if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
+ softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF16UI(&commonNaN);
+ } else {
+ uiZ = packToF16UI(sign, 0x1F, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig16 = softfloat_shortShiftRightJam64(sig, 49);
+ if (! (exp | sig16)) {
+ return packToF16UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp -= 0x3FF1;
+ if (sizeof (int16_t) < sizeof (int32_t)) {
+ if (exp < -0x40) exp = -0x40;
+ }
+ return softfloat_roundPackToF16(sign, exp, sig16, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_f32.cc b/src/cpu/softfloat3e/extF80_to_f32.cc
new file mode 100644
index 0000000000..558df4c235
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_f32.cc
@@ -0,0 +1,89 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 extF80_to_f32(extFloat80_t a, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ struct commonNaN commonNaN;
+ uint32_t uiZ, sig32;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FFF) {
+ if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
+ softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF32UI(&commonNaN);
+ } else {
+ uiZ = packToF32UI(sign, 0xFF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig32 = softfloat_shortShiftRightJam64(sig, 33);
+ if (! (exp | sig32)) {
+ return packToF32UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp -= 0x3F81;
+ if (sizeof (int16_t) < sizeof (int32_t)) {
+ if (exp < -0x1000) exp = -0x1000;
+ }
+ return softfloat_roundPackToF32(sign, exp, sig32, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_f64.cc b/src/cpu/softfloat3e/extF80_to_f64.cc
new file mode 100644
index 0000000000..4ba4174e3c
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_f64.cc
@@ -0,0 +1,89 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 extF80_to_f64(extFloat80_t a, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ uint64_t uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ struct commonNaN commonNaN;
+ uint64_t uiZ;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ uiA0 = a.signif;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! (exp | sig)) {
+ return packToF64UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FFF) {
+ if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
+ softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF64UI(&commonNaN);
+ } else {
+ uiZ = packToF64UI(sign, 0x7FF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig = softfloat_shortShiftRightJam64(sig, 1);
+ exp -= 0x3C01;
+ if (sizeof (int16_t) < sizeof (int32_t)) {
+ if (exp < -0x1000) exp = -0x1000;
+ }
+ return softfloat_roundPackToF64(sign, exp, sig, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_i32.cc b/src/cpu/softfloat3e/extF80_to_i32.cc
new file mode 100644
index 0000000000..ea6c94484c
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_i32.cc
@@ -0,0 +1,82 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t extF80_to_i32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i32_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
+ if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) {
+#if (i32_fromNaN == i32_fromPosOverflow)
+ sign = 0;
+#elif (i32_fromNaN == i32_fromNegOverflow)
+ sign = 1;
+#else
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i32_fromNaN;
+#endif
+ }
+#endif
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x4032 - exp;
+ if (shiftDist <= 0) shiftDist = 1;
+ sig = softfloat_shiftRightJam64(sig, shiftDist);
+ return softfloat_roundToI32(sign, sig, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc
new file mode 100644
index 0000000000..42415c4599
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc
@@ -0,0 +1,93 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t extF80_to_i32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+ bool sign;
+ int32_t absZ;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i32_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x403E - exp;
+ if (64 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signExtF80UI64(uiA64);
+ if (shiftDist < 33) {
+ if ((uiA64 == packToExtF80UI64(1, 0x401E)) && (sig < UINT64_C(0x8000000100000000))) {
+ if (exact && (sig & UINT64_C(0x00000000FFFFFFFF))) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return -0x7FFFFFFF - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
+ ? i32_fromNaN
+ : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ absZ = sig>>shiftDist;
+ if (exact && ((uint64_t) (uint32_t) absZ<
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t extF80_to_i64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+ uint64_t sigExtra;
+ struct uint64_extra sig64Extra;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i64_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x403E - exp;
+ if (shiftDist <= 0) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (shiftDist) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sigExtra = 0;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist);
+ sig = sig64Extra.v;
+ sigExtra = sig64Extra.extra;
+ }
+ return softfloat_roundToI64(sign, sig, sigExtra, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc
new file mode 100644
index 0000000000..3500b20d27
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc
@@ -0,0 +1,90 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t extF80_to_i64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+ bool sign;
+ int64_t absZ;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i64_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x403E - exp;
+ if (64 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signExtF80UI64(uiA64);
+ if (shiftDist <= 0) {
+ if ((uiA64 == packToExtF80UI64(1, 0x403E)) && (sig == UINT64_C(0x8000000000000000))) {
+ return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ absZ = sig>>shiftDist;
+ if (exact && (uint64_t) (sig<<(-shiftDist & 63))) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return sign ? -absZ : absZ;
+}
diff --git a/src/cpu/softfloat3e/extF80_to_ui32.cc b/src/cpu/softfloat3e/extF80_to_ui32.cc
new file mode 100644
index 0000000000..449cafa884
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_ui32.cc
@@ -0,0 +1,83 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t
+ extF80_to_ui32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui32_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
+ if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) {
+#if (ui32_fromNaN == ui32_fromPosOverflow)
+ sign = 0;
+#elif (ui32_fromNaN == ui32_fromNegOverflow)
+ sign = 1;
+#else
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui32_fromNaN;
+#endif
+ }
+#endif
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x4032 - exp;
+ if (shiftDist <= 0) shiftDist = 1;
+ sig = softfloat_shiftRightJam64(sig, shiftDist);
+ return softfloat_roundToUI32(sign, sig, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc
new file mode 100644
index 0000000000..7ef1001390
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc
@@ -0,0 +1,87 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t extF80_to_ui32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+ bool sign;
+ uint32_t z;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui32_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x403E - exp;
+ if (64 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signExtF80UI64(uiA64);
+ if (sign || (shiftDist < 32)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
+ ? ui32_fromNaN
+ : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ z = sig>>shiftDist;
+ if (exact && ((uint64_t) z<
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t extF80_to_ui64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ bool sign;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+ uint64_t sigExtra;
+ struct uint64_extra sig64Extra;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui64_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ sign = signExtF80UI64(uiA64);
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x403E - exp;
+ if (shiftDist < 0) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
+ ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sigExtra = 0;
+ if (shiftDist) {
+ sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist);
+ sig = sig64Extra.v;
+ sigExtra = sig64Extra.extra;
+ }
+ return softfloat_roundToUI64(sign, sig, sigExtra, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc
new file mode 100644
index 0000000000..78b058754d
--- /dev/null
+++ b/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc
@@ -0,0 +1,87 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t extF80_to_ui64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint16_t uiA64;
+ int32_t exp;
+ uint64_t sig;
+ int32_t shiftDist;
+ bool sign;
+ uint64_t z;
+
+ // handle unsupported extended double-precision floating encodings
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui64_fromNaN;
+ }
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.signExp;
+ exp = expExtF80UI64(uiA64);
+ sig = a.signif;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x403E - exp;
+ if (64 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signExtF80UI64(uiA64);
+ if (sign || (shiftDist < 0)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
+ ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ z = sig>>shiftDist;
+ if (exact && (z<
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+extern float128_t
+ softfloat_addMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *);
+extern float128_t
+ softfloat_subMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *);
+
+float128_t f128_add(float128_t a, float128_t b, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool signA;
+ uint64_t uiB64, uiB0;
+ bool signB;
+
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ signA = signF128UI64(uiA64);
+
+ uiB64 = b.v64;
+ uiB0 = b.v0;
+ signB = signF128UI64(uiB64);
+
+ if (signA == signB) {
+ return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
+ } else {
+ return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
+ }
+}
+
+float128_t f128_sub(float128_t a, float128_t b, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool signA;
+ uint64_t uiB64, uiB0;
+ bool signB;
+
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ signA = signF128UI64(uiA64);
+
+ uiB64 = b.v64;
+ uiB0 = b.v0;
+ signB = signF128UI64(uiB64);
+
+ if (signA == signB) {
+ return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
+ } else {
+ return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
+ }
+}
diff --git a/src/cpu/softfloat3e/f128_div.cc b/src/cpu/softfloat3e/f128_div.cc
new file mode 100644
index 0000000000..837eb15aa0
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_div.cc
@@ -0,0 +1,187 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f128_div(float128_t a, float128_t b, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool signA;
+ int32_t expA;
+ struct uint128 sigA;
+ uint64_t uiB64, uiB0;
+ bool signB;
+ int32_t expB;
+ struct uint128 sigB;
+ bool signZ;
+ struct exp32_sig128 normExpSig;
+ int32_t expZ;
+ struct uint128 rem;
+ uint32_t recip32;
+ int ix;
+ uint64_t q64;
+ uint32_t q;
+ struct uint128 term;
+ uint32_t qs[3];
+ uint64_t sigZExtra;
+ struct uint128 sigZ, uiZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ signA = signF128UI64(uiA64);
+ expA = expF128UI64(uiA64);
+ sigA.v64 = fracF128UI64(uiA64);
+ sigA.v0 = uiA0;
+ uiB64 = b.v64;
+ uiB0 = b.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(status, softfloat_flag_infinite);
+ goto infinity;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ if (! expA) {
+ if (! (sigA.v64 | sigA.v0)) goto zero;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ 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 = (uint64_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) ((uint64_t) q<<60);
+ term = softfloat_shortShiftLeft128(0, qs[1], 54);
+ sigZ = softfloat_add128((uint64_t) qs[2]<<19, ((uint64_t) qs[0]<<25) + (q>>4), term.v64, term.v0);
+ return
+ softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ.v64 = defaultNaNF128UI64;
+ uiZ.v0 = defaultNaNF128UI0;
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infinity:
+ uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0);
+ uiZ.v0 = 0;
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ uiZ.v64 = packToF128UI64(signZ, 0, 0);
+ uiZ.v0 = 0;
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f128_mul.cc b/src/cpu/softfloat3e/f128_mul.cc
new file mode 100644
index 0000000000..fd63a4590a
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_mul.cc
@@ -0,0 +1,148 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "primitiveTypes.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f128_mul(float128_t a, float128_t b, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool signA;
+ int32_t expA;
+ struct uint128 sigA;
+ uint64_t uiB64, uiB0;
+ bool signB;
+ int32_t expB;
+ struct uint128 sigB;
+ bool signZ;
+ uint64_t magBits;
+ struct exp32_sig128 normExpSig;
+ int32_t expZ;
+ uint64_t sig256Z[4];
+ uint64_t sigZExtra;
+ struct uint128 sigZ;
+ struct uint128_extra sig128Extra;
+ struct uint128 uiZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ signA = signF128UI64(uiA64);
+ expA = expF128UI64(uiA64);
+ sigA.v64 = fracF128UI64(uiA64);
+ sigA.v0 = uiA0;
+ uiB64 = b.v64;
+ uiB0 = b.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;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! (sigB.v64 | sigB.v0)) goto zero;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ 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(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infArg:
+ if (! magBits) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ.v64 = defaultNaNF128UI64;
+ uiZ.v0 = defaultNaNF128UI0;
+ return uiZ;
+ }
+ uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0);
+ uiZ.v0 = 0;
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ uiZ.v64 = packToF128UI64(signZ, 0, 0);
+ uiZ.v0 = 0;
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f128_mulAdd.cc b/src/cpu/softfloat3e/f128_mulAdd.cc
new file mode 100644
index 0000000000..749342f5f1
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_mulAdd.cc
@@ -0,0 +1,332 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "primitiveTypes.h"
+#include "softfloat.h"
+#include "specialize.h"
+
+float128_t f128_mulAdd(float128_t a, float128_t b, float128_t c, uint8_t op, struct softfloat_status_t *status)
+{
+ bool signA;
+ int32_t expA;
+ struct uint128 sigA;
+ bool signB;
+ int32_t expB;
+ struct uint128 sigB;
+ bool signC;
+ int32_t expC;
+ struct uint128 sigC;
+ bool signZ;
+ uint64_t magBits;
+ struct uint128 uiZ;
+ struct exp32_sig128 normExpSig;
+ int32_t expZ;
+ uint64_t sig256Z[4];
+ struct uint128 sigZ;
+ int32_t shiftDist, expDiff;
+ struct uint128 x128;
+ uint64_t sig256C[4];
+ static uint64_t zero256[4] = INIT_UINTM4(0, 0, 0, 0);
+ uint64_t sigZExtra, sig256Z0;
+ uint64_t uiA64, uiA0;
+ uint64_t uiB64, uiB0;
+ uint64_t uiC64, uiC0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ uiB64 = b.v64;
+ uiB0 = b.v0;
+ uiC64 = c.v64;
+ uiC0 = c.v0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF128UI64(uiA64);
+ expA = expF128UI64(uiA64);
+ sigA.v64 = fracF128UI64(uiA64);
+ sigA.v0 = uiA0;
+ signB = signF128UI64(uiB64);
+ expB = expF128UI64(uiB64);
+ sigB.v64 = fracF128UI64(uiB64);
+ sigB.v0 = uiB0;
+ signC = signF128UI64(uiC64) ^ ((op & softfloat_mulAdd_subC) != 0);
+ expC = expF128UI64(uiC64);
+ sigC.v64 = fracF128UI64(uiC64);
+ sigC.v0 = uiC0;
+ signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) {
+ goto propagateNaN_ABC;
+ }
+ magBits = expB | sigB.v64 | sigB.v0;
+ goto infProdArg;
+ }
+ if (expB == 0x7FFF) {
+ if (sigB.v64 | sigB.v0) goto propagateNaN_ABC;
+ magBits = expA | sigA.v64 | sigA.v0;
+ goto infProdArg;
+ }
+ if (expC == 0x7FFF) {
+ if (sigC.v64 | sigC.v0) {
+ uiZ.v64 = 0;
+ uiZ.v0 = 0;
+ goto propagateNaN_ZC;
+ }
+ uiZ.v64 = uiC64;
+ uiZ.v0 = uiC0;
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! (sigA.v64 | sigA.v0)) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! (sigB.v64 | sigB.v0)) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA + expB - 0x3FFE;
+ sigA.v64 |= UINT64_C(0x0001000000000000);
+ sigB.v64 |= UINT64_C(0x0001000000000000);
+ sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 8);
+ sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 15);
+ softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z);
+ sigZ.v64 = sig256Z[indexWord(4, 3)];
+ sigZ.v0 = sig256Z[indexWord(4, 2)];
+ shiftDist = 0;
+ if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) {
+ --expZ;
+ shiftDist = -1;
+ }
+ if (! expC) {
+ if (! (sigC.v64 | sigC.v0)) {
+ shiftDist += 8;
+ goto sigZ;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF128Sig(sigC.v64, sigC.v0);
+ expC = normExpSig.exp;
+ sigC = normExpSig.sig;
+ }
+ sigC.v64 |= UINT64_C(0x0001000000000000);
+ sigC = softfloat_shortShiftLeft128(sigC.v64, sigC.v0, 8);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expZ - expC;
+ if (expDiff < 0) {
+ expZ = expC;
+ if ((signZ == signC) || (expDiff < -1)) {
+ shiftDist -= expDiff;
+ if (shiftDist) {
+ sigZ = softfloat_shiftRightJam128(sigZ.v64, sigZ.v0, shiftDist);
+ }
+ } else {
+ if (! shiftDist) {
+ x128 = softfloat_shortShiftRight128(sig256Z[indexWord(4, 1)], sig256Z[indexWord(4, 0)], 1);
+ sig256Z[indexWord(4, 1)] = (sigZ.v0<<63) | x128.v64;
+ sig256Z[indexWord(4, 0)] = x128.v0;
+ sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, 1);
+ sig256Z[indexWord(4, 3)] = sigZ.v64;
+ sig256Z[indexWord(4, 2)] = sigZ.v0;
+ }
+ }
+ } else {
+ if (shiftDist) softfloat_add256M(sig256Z, sig256Z, sig256Z);
+ if (! expDiff) {
+ sigZ.v64 = sig256Z[indexWord(4, 3)];
+ sigZ.v0 = sig256Z[indexWord(4, 2)];
+ } else {
+ sig256C[indexWord(4, 3)] = sigC.v64;
+ sig256C[indexWord(4, 2)] = sigC.v0;
+ sig256C[indexWord(4, 1)] = 0;
+ sig256C[indexWord(4, 0)] = 0;
+ softfloat_shiftRightJam256M(sig256C, expDiff, sig256C);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 8;
+ if (signZ == signC) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff <= 0) {
+ sigZ = softfloat_add128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0);
+ } else {
+ softfloat_add256M(sig256Z, sig256C, sig256Z);
+ sigZ.v64 = sig256Z[indexWord(4, 3)];
+ sigZ.v0 = sig256Z[indexWord(4, 2)];
+ }
+ if (sigZ.v64 & UINT64_C(0x0200000000000000)) {
+ ++expZ;
+ shiftDist = 9;
+ }
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff < 0) {
+ signZ = signC;
+ if (expDiff < -1) {
+ sigZ = softfloat_sub128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0);
+ sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)];
+ if (sigZExtra) {
+ sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1);
+ }
+ if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) {
+ --expZ;
+ shiftDist = 7;
+ }
+ goto shiftRightRoundPack;
+ } else {
+ sig256C[indexWord(4, 3)] = sigC.v64;
+ sig256C[indexWord(4, 2)] = sigC.v0;
+ sig256C[indexWord(4, 1)] = 0;
+ sig256C[indexWord(4, 0)] = 0;
+ softfloat_sub256M(sig256C, sig256Z, sig256Z);
+ }
+ } else if (! expDiff) {
+ sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, sigC.v64, sigC.v0);
+ if (! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord(4, 1)] && ! sig256Z[indexWord(4, 0)]) {
+ goto completeCancellation;
+ }
+ sig256Z[indexWord(4, 3)] = sigZ.v64;
+ sig256Z[indexWord(4, 2)] = sigZ.v0;
+ if (sigZ.v64 & UINT64_C(0x8000000000000000)) {
+ signZ = ! signZ;
+ softfloat_sub256M(zero256, sig256Z, sig256Z);
+ }
+ } else {
+ softfloat_sub256M(sig256Z, sig256C, sig256Z);
+ if (1 < expDiff) {
+ sigZ.v64 = sig256Z[indexWord(4, 3)];
+ sigZ.v0 = sig256Z[indexWord(4, 2)];
+ if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) {
+ --expZ;
+ shiftDist = 7;
+ }
+ goto sigZ;
+ }
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sigZ.v64 = sig256Z[indexWord(4, 3)];
+ sigZ.v0 = sig256Z[indexWord(4, 2)];
+ sigZExtra = sig256Z[indexWord(4, 1)];
+ sig256Z0 = sig256Z[indexWord(4, 0)];
+ if (sigZ.v64) {
+ if (sig256Z0) sigZExtra |= 1;
+ } else {
+ expZ -= 64;
+ sigZ.v64 = sigZ.v0;
+ sigZ.v0 = sigZExtra;
+ sigZExtra = sig256Z0;
+ if (! sigZ.v64) {
+ expZ -= 64;
+ sigZ.v64 = sigZ.v0;
+ sigZ.v0 = sigZExtra;
+ sigZExtra = 0;
+ if (! sigZ.v64) {
+ expZ -= 64;
+ sigZ.v64 = sigZ.v0;
+ sigZ.v0 = 0;
+ }
+ }
+ }
+ shiftDist = softfloat_countLeadingZeros64(sigZ.v64);
+ expZ += 7 - shiftDist;
+ shiftDist = 15 - shiftDist;
+ if (0 < shiftDist) goto shiftRightRoundPack;
+ if (shiftDist) {
+ shiftDist = -shiftDist;
+ sigZ = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, shiftDist);
+ x128 = softfloat_shortShiftLeft128(0, sigZExtra, shiftDist);
+ sigZ.v0 |= x128.v64;
+ sigZExtra = x128.v0;
+ }
+ goto roundPack;
+ }
+ sigZ:
+ sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)];
+ shiftRightRoundPack:
+ sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0);
+ sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, shiftDist);
+ roundPack:
+ return softfloat_roundPackToF128(signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN_ABC:
+ uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
+ goto propagateNaN_ZC;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infProdArg:
+ if ((sigC.v64 | sigC.v0) && expC == 0x7FFF) goto propagateNaN_ZC;
+ if (magBits) {
+ uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0);
+ uiZ.v0 = 0;
+ if (expC != 0x7FFF) return uiZ;
+ if (signZ == signC) return uiZ;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ.v64 = defaultNaNF128UI64;
+ uiZ.v0 = defaultNaNF128UI0;
+ propagateNaN_ZC:
+ uiZ = softfloat_propagateNaNF128UI(uiZ.v64, uiZ.v0, uiC64, uiC0, status);
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zeroProd:
+ uiZ.v64 = uiC64;
+ uiZ.v0 = uiC0;
+ if (! (expC | sigC.v64 | sigC.v0) && (signZ != signC)) {
+ completeCancellation:
+ uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0);
+ uiZ.v0 = 0;
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f128_roundToInt.cc b/src/cpu/softfloat3e/f128_roundToInt.cc
new file mode 100644
index 0000000000..c3b7287040
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_roundToInt.cc
@@ -0,0 +1,142 @@
+/*============================================================================
+
+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, 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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t
+ f128_roundToInt(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ int32_t exp;
+ struct uint128 uiZ;
+ uint64_t lastBitMask0, roundBitsMask;
+ bool roundNearEven;
+ uint64_t lastBitMask64;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ exp = expF128UI64(uiA64);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (0x402F <= exp) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (0x406F <= exp) {
+ if ((exp == 0x7FFF) && (fracF128UI64(uiA64) | uiA0)) {
+ uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, 0, 0, status);
+ return uiZ;
+ }
+ return a;
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ lastBitMask0 = (uint64_t) 2<<(0x406E - exp);
+ roundBitsMask = lastBitMask0 - 1;
+ uiZ.v64 = uiA64;
+ uiZ.v0 = uiA0;
+ roundNearEven = (roundingMode == softfloat_round_near_even);
+ if (roundNearEven || (roundingMode == softfloat_round_near_maxMag)) {
+ if (exp == 0x402F) {
+ if (UINT64_C(0x8000000000000000) <= uiZ.v0) {
+ ++uiZ.v64;
+ if (roundNearEven && (uiZ.v0 == UINT64_C(0x8000000000000000))) {
+ uiZ.v64 &= ~1;
+ }
+ }
+ } else {
+ uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, lastBitMask0>>1);
+ if (roundNearEven && !(uiZ.v0 & roundBitsMask)) {
+ uiZ.v0 &= ~lastBitMask0;
+ }
+ }
+ } else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) {
+ uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, roundBitsMask);
+ }
+ uiZ.v0 &= ~roundBitsMask;
+ lastBitMask64 = !lastBitMask0;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (exp < 0x3FFF) {
+ if (!((uiA64 & UINT64_C(0x7FFFFFFFFFFFFFFF)) | uiA0)) return a;
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ uiZ.v64 = uiA64 & packToF128UI64(1, 0, 0);
+ uiZ.v0 = 0;
+ switch (roundingMode) {
+ case softfloat_round_near_even:
+ if (!(fracF128UI64(uiA64) | uiA0)) break;
+ case softfloat_round_near_maxMag:
+ if (exp == 0x3FFE) uiZ.v64 |= packToF128UI64(0, 0x3FFF, 0);
+ break;
+ case softfloat_round_min:
+ if (uiZ.v64) uiZ.v64 = packToF128UI64(1, 0x3FFF, 0);
+ break;
+ case softfloat_round_max:
+ if (!uiZ.v64) uiZ.v64 = packToF128UI64(0, 0x3FFF, 0);
+ break;
+ }
+ return uiZ;
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ uiZ.v64 = uiA64;
+ uiZ.v0 = 0;
+ lastBitMask64 = (uint64_t) 1<<(0x402F - exp);
+ roundBitsMask = lastBitMask64 - 1;
+ if (roundingMode == softfloat_round_near_maxMag) {
+ uiZ.v64 += lastBitMask64>>1;
+ } else if (roundingMode == softfloat_round_near_even) {
+ uiZ.v64 += lastBitMask64>>1;
+ if (!((uiZ.v64 & roundBitsMask) | uiA0)) {
+ uiZ.v64 &= ~lastBitMask64;
+ }
+ } else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) {
+ uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask;
+ }
+ uiZ.v64 &= ~roundBitsMask;
+ lastBitMask0 = 0;
+ }
+ if ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) {
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f128_to_extF80.cc b/src/cpu/softfloat3e/f128_to_extF80.cc
new file mode 100644
index 0000000000..916820bc9d
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_extF80.cc
@@ -0,0 +1,94 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t f128_to_extF80(float128_t a, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t frac64, frac0;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ uint16_t uiZ64;
+ uint64_t uiZ0;
+ struct exp32_sig128 normExpSig;
+ struct uint128 sig128;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ frac64 = fracF128UI64(uiA64);
+ frac0 = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FFF) {
+ if (frac64 | frac0) {
+ softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToExtF80UI(&commonNaN);
+ uiZ64 = uiZ.v64;
+ uiZ0 = uiZ.v0;
+ } else {
+ uiZ64 = packToExtF80UI64(sign, 0x7FFF);
+ uiZ0 = UINT64_C(0x8000000000000000);
+ }
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! (frac64 | frac0)) {
+ return packToExtF80(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF128Sig(frac64, frac0);
+ exp = normExpSig.exp;
+ frac64 = normExpSig.sig.v64;
+ frac0 = normExpSig.sig.v0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig128 = softfloat_shortShiftLeft128(frac64 | UINT64_C(0x0001000000000000), frac0, 15);
+ return softfloat_roundPackToExtF80(sign, exp, sig128.v64, sig128.v0, 80, status);
+}
diff --git a/src/cpu/softfloat3e/f128_to_f32.cc b/src/cpu/softfloat3e/f128_to_f32.cc
new file mode 100644
index 0000000000..485d68a0ce
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_f32.cc
@@ -0,0 +1,83 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f128_to_f32(float128_t a, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t frac64;
+ struct commonNaN commonNaN;
+ uint32_t uiZ, frac32;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ frac64 = fracF128UI64(uiA64) | (uiA0 != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FFF) {
+ if (frac64) {
+ softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF32UI(&commonNaN);
+ } else {
+ uiZ = packToF32UI(sign, 0xFF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac32 = softfloat_shortShiftRightJam64(frac64, 18);
+ if (! (exp | frac32)) {
+ return packToF32UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp -= 0x3F81;
+ if (sizeof (int16_t) < sizeof (int32_t)) {
+ if (exp < -0x1000) exp = -0x1000;
+ }
+ return softfloat_roundPackToF32(sign, exp, frac32 | 0x40000000, status);
+}
diff --git a/src/cpu/softfloat3e/f128_to_f64.cc b/src/cpu/softfloat3e/f128_to_f64.cc
new file mode 100644
index 0000000000..0809c7102c
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_f64.cc
@@ -0,0 +1,87 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f128_to_f64(float128_t a, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t frac64, frac0;
+ struct commonNaN commonNaN;
+ uint64_t uiZ;
+ struct uint128 frac128;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ frac64 = fracF128UI64(uiA64);
+ frac0 = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FFF) {
+ if (frac64 | frac0) {
+ softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF64UI(&commonNaN);
+ } else {
+ uiZ = packToF64UI(sign, 0x7FF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac128 = softfloat_shortShiftLeft128(frac64, frac0, 14);
+ frac64 = frac128.v64 | (frac128.v0 != 0);
+ if (! (exp | frac64)) {
+ return packToF64UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp -= 0x3C01;
+ if (sizeof (int16_t) < sizeof (int32_t)) {
+ if (exp < -0x1000) exp = -0x1000;
+ }
+ return
+ softfloat_roundPackToF64(sign, exp, frac64 | UINT64_C(0x4000000000000000), status);
+}
diff --git a/src/cpu/softfloat3e/f128_to_i32.cc b/src/cpu/softfloat3e/f128_to_i32.cc
new file mode 100644
index 0000000000..68cf2b3a70
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_i32.cc
@@ -0,0 +1,80 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f128_to_i32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig64, sig0;
+ int32_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.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(status, 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(sign, sig64, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc b/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc
new file mode 100644
index 0000000000..a62233d4df
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc
@@ -0,0 +1,89 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f128_to_i32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ int32_t exp;
+ uint64_t sig64;
+ int32_t shiftDist;
+ bool sign;
+ int32_t absZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ exp = expF128UI64(uiA64);
+ sig64 = fracF128UI64(uiA64) | (uiA0 != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x402F - exp;
+ if (49 <= shiftDist) {
+ if (exact && (exp | sig64)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF128UI64(uiA64);
+ if (shiftDist < 18) {
+ if (sign && (shiftDist == 17) && (sig64 < UINT64_C(0x0000000000020000))) {
+ if (exact && sig64) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return -0x7FFFFFFF - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && sig64 ? i32_fromNaN
+ : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig64 |= UINT64_C(0x0001000000000000);
+ absZ = sig64>>shiftDist;
+ if (exact && ((uint64_t) (uint32_t) absZ<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f128_to_i64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig64, sig0;
+ int32_t shiftDist;
+ struct uint128 sig128;
+ struct uint64_extra sigExtra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ sig64 = fracF128UI64(uiA64);
+ sig0 = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x402F - exp;
+ if (shiftDist <= 0) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (shiftDist < -15) {
+ softfloat_raiseFlags(status, 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(sign, sig64, sig0, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc b/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc
new file mode 100644
index 0000000000..edeccf1828
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc
@@ -0,0 +1,104 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f128_to_i64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig64, sig0;
+ int32_t shiftDist;
+ int8_t negShiftDist;
+ uint64_t absZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ sig64 = fracF128UI64(uiA64);
+ sig0 = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x402F - exp;
+ if (shiftDist < 0) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (shiftDist < -14) {
+ if ((uiA64 == UINT64_C(0xC03E000000000000)) && (sig0 < UINT64_C(0x0002000000000000))) {
+ if (exact && sig0) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x7FFF) && (sig64 | sig0)
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sig64 |= UINT64_C(0x0001000000000000);
+ negShiftDist = -shiftDist;
+ absZ = sig64<>(shiftDist & 63);
+ if (exact && (uint64_t) (sig0<>shiftDist;
+ if (exact && (sig0 || (absZ<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f128_to_ui32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig64;
+ int32_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.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(status, 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, status);
+}
+
diff --git a/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc b/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc
new file mode 100644
index 0000000000..96007f6a1d
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc
@@ -0,0 +1,83 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f128_to_ui32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ int32_t exp;
+ uint64_t sig64;
+ int32_t shiftDist;
+ bool sign;
+ uint32_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ exp = expF128UI64(uiA64);
+ sig64 = fracF128UI64(uiA64) | (uiA0 != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x402F - exp;
+ if (49 <= shiftDist) {
+ if (exact && (exp | sig64)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF128UI64(uiA64);
+ if (sign || (shiftDist < 17)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FFF) && sig64 ? ui32_fromNaN
+ : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig64 |= UINT64_C(0x0001000000000000);
+ z = sig64>>shiftDist;
+ if (exact && ((uint64_t) z<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f128_to_ui64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig64, sig0;
+ int32_t shiftDist;
+ struct uint128 sig128;
+ struct uint64_extra sigExtra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ sig64 = fracF128UI64(uiA64);
+ sig0 = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x402F - exp;
+ if (shiftDist <= 0) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (shiftDist < -15) {
+ softfloat_raiseFlags(status, 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(sign, sig64, sig0, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc b/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc
new file mode 100644
index 0000000000..8d30420b02
--- /dev/null
+++ b/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc
@@ -0,0 +1,99 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f128_to_ui64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
+{
+ uint64_t uiA64, uiA0;
+ bool sign;
+ int32_t exp;
+ uint64_t sig64, sig0;
+ int32_t shiftDist;
+ int8_t negShiftDist;
+ uint64_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA64 = a.v64;
+ uiA0 = a.v0;
+ sign = signF128UI64(uiA64);
+ exp = expF128UI64(uiA64);
+ sig64 = fracF128UI64(uiA64);
+ sig0 = uiA0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x402F - exp;
+ if (shiftDist < 0) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (sign || (shiftDist < -15)) goto invalid;
+ sig64 |= UINT64_C(0x0001000000000000);
+ negShiftDist = -shiftDist;
+ z = sig64<>(shiftDist & 63);
+ if (exact && (uint64_t) (sig0<>shiftDist;
+ if (exact && (sig0 || (z<
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+extern float16 softfloat_addMagsF16(uint16_t, uint16_t, struct softfloat_status_t *);
+extern float16 softfloat_subMagsF16(uint16_t, uint16_t, struct softfloat_status_t *);
+
+float16 f16_add(float16 a, float16 b, struct softfloat_status_t *status)
+{
+ if (signF16UI((uint16_t) a ^ (uint16_t) b)) {
+ return softfloat_subMagsF16(a, b, status);
+ } else {
+ return softfloat_addMagsF16(a, b, status);
+ }
+}
+
+float16 f16_sub(float16 a, float16 b, struct softfloat_status_t *status)
+{
+ if (signF16UI((uint16_t) a ^ (uint16_t) b)) {
+ return softfloat_addMagsF16(a, b, status);
+ } else {
+ return softfloat_subMagsF16(a, b, status);
+ }
+}
diff --git a/src/cpu/softfloat3e/f16_class.c b/src/cpu/softfloat3e/f16_class.c
new file mode 100644
index 0000000000..b375c1544e
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_class.c
@@ -0,0 +1,64 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+softfloat_class_t f16_class(float16 a)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+
+ signA = signF16UI(a);
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+
+ if (expA == 0x1F) {
+ if (sigA == 0)
+ return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
+
+ return (sigA & 0x200) ? softfloat_QNaN : softfloat_SNaN;
+ }
+
+ if (expA == 0) {
+ if (sigA == 0) return softfloat_zero;
+ return softfloat_denormal;
+ }
+
+ return softfloat_normalized;
+}
diff --git a/src/cpu/softfloat3e/f16_compare.c b/src/cpu/softfloat3e/f16_compare.c
new file mode 100644
index 0000000000..1cfd56bec9
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_compare.c
@@ -0,0 +1,92 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two half precision floating point numbers. Returns
+| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
+| the value 'a' is less than the corresponding value `b',
+| 'float_relation_greater' if the value 'a' is greater than the corresponding
+| value `b', or 'float_relation_unordered' otherwise.
+*----------------------------------------------------------------------------*/
+
+int f16_compare(float16 a, float16 b, bool quiet, struct softfloat_status_t *status)
+{
+ softfloat_class_t aClass;
+ softfloat_class_t bClass;
+ bool signA;
+ bool signB;
+
+ aClass = f16_class(a);
+ bClass = f16_class(b);
+
+ if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
+ if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_denormal) {
+ if (softfloat_denormalsAreZeros(status))
+ a = a & 0x8000;
+ else
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+
+ if (bClass == softfloat_denormal) {
+ if (softfloat_denormalsAreZeros(status))
+ b = b & 0x8000;
+ else
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+
+ if ((a == b) || ((uint16_t) ((a | b)<<1) == 0)) return softfloat_relation_equal;
+
+ signA = signF16UI(a);
+ signB = signF16UI(b);
+ if (signA != signB)
+ return (signA) ? softfloat_relation_less : softfloat_relation_greater;
+
+ if (signA ^ (a < b)) return softfloat_relation_less;
+ return softfloat_relation_greater;
+}
diff --git a/src/cpu/softfloat3e/f16_div.c b/src/cpu/softfloat3e/f16_div.c
new file mode 100644
index 0000000000..c91760b03b
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_div.c
@@ -0,0 +1,149 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+#define SOFTFLOAT_FAST_DIV32TO16 1
+
+extern const uint16_t softfloat_approxRecip_1k0s[];
+extern const uint16_t softfloat_approxRecip_1k1s[];
+
+float16 f16_div(float16 a, float16 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+ bool signB;
+ int8_t expB;
+ uint16_t sigB;
+ bool signZ;
+ struct exp8_sig16 normExpSig;
+ int8_t expZ;
+#ifdef SOFTFLOAT_FAST_DIV32TO16
+ uint32_t sig32A;
+ uint16_t sigZ;
+#endif
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF16UI(a);
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+ signB = signF16UI(b);
+ expB = expF16UI(b);
+ sigB = fracF16UI(b);
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x1F) {
+ if (sigA) goto propagateNaN;
+ if (expB == 0x1F) {
+ if (sigB) goto propagateNaN;
+ goto invalid;
+ }
+ if (sigB && !expB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infinity;
+ }
+ if (expB == 0x1F) {
+ if (sigB) goto propagateNaN;
+ if (sigA && !expA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expB) {
+ if (! sigB) {
+ if (! (expA | sigA)) goto invalid;
+ softfloat_raiseFlags(status, softfloat_flag_infinite);
+ goto infinity;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ if (! expA) {
+ if (! sigA) goto zero;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA - expB + 0xE;
+ sigA |= 0x0400;
+ sigB |= 0x0400;
+#ifdef SOFTFLOAT_FAST_DIV32TO16
+ if (sigA < sigB) {
+ --expZ;
+ sig32A = (uint32_t) sigA<<15;
+ } else {
+ sig32A = (uint32_t) sigA<<14;
+ }
+ sigZ = sig32A / sigB;
+ if (! (sigZ & 7)) sigZ |= ((uint32_t) sigB * sigZ != sig32A);
+#endif
+ return softfloat_roundPackToF16(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF16UI(a, b, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF16UI;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infinity:
+ return packToF16UI(signZ, 0x1F, 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ return packToF16UI(signZ, 0, 0);
+}
diff --git a/src/cpu/softfloat3e/f16_getExp.c b/src/cpu/softfloat3e/f16_getExp.c
new file mode 100644
index 0000000000..dfade995f7
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_getExp.c
@@ -0,0 +1,73 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the exponent portion of half-precision floating-point value 'a',
+| and returns the result as a half-precision floating-point value
+| representing unbiased integer exponent. The operation is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float16 f16_getExp(float16 a, struct softfloat_status_t *status)
+{
+ int8_t expA;
+ uint16_t sigA;
+ struct exp8_sig16 normExpSig;
+
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+
+ if (expA == 0x1F) {
+ if (sigA) return softfloat_propagateNaNF16UI(a, 0, status);
+ return (float16)packToF32UI(0, 0x1F, 0);
+ }
+
+ if (! expA) {
+ if (! sigA || softfloat_denormalsAreZeros(status))
+ return (float16)packToF32UI(1, 0x1F, 0);
+
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigA);
+ expA = normExpSig.exp;
+ }
+
+ return i32_to_f16((int32_t)(expA) - 0xF, status);
+}
diff --git a/src/cpu/softfloat3e/f16_getMant.c b/src/cpu/softfloat3e/f16_getMant.c
new file mode 100644
index 0000000000..f0d8d54821
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_getMant.c
@@ -0,0 +1,108 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the mantissa of half-precision floating-point value 'a' and
+| returns the result as a half-precision floating-point after applying
+| the mantissa interval normalization and sign control. The operation is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float16 f16_getMant(float16 a, struct softfloat_status_t *status, int sign_ctrl, int interv)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+ struct exp8_sig16 normExpSig;
+
+ signA = signF16UI(a);
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+
+ if (expA == 0x1F) {
+ if (sigA) return softfloat_propagateNaNF16UI(a, 0, status);
+ if (signA) {
+ if (sign_ctrl & 0x2) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF16UI;
+ }
+ }
+ return packToF16UI(~sign_ctrl & signA, 0x1F, 0);
+ }
+
+ if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) {
+ return packToF16UI(~sign_ctrl & signA, 0x1F, 0);
+ }
+
+ if (signA) {
+ if (sign_ctrl & 0x2) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF16UI;
+ }
+ }
+
+ if (expA == 0) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ sigA &= 0x3ff;
+ }
+
+ switch(interv) {
+ case 0x0: // interval [1,2)
+ expA = 0xF;
+ break;
+ case 0x1: // interval [1/2,2)
+ expA -= 0xF;
+ expA = 0xF - (expA & 0x1);
+ break;
+ case 0x2: // interval [1/2,1)
+ expA = 0xE;
+ break;
+ case 0x3: // interval [3/4,3/2)
+ expA = 0xF - ((sigA >> 9) & 0x1);
+ break;
+ }
+
+ return packToF16UI(~sign_ctrl & signA, expA, sigA);
+}
diff --git a/src/cpu/softfloat3e/f16_minmax.c b/src/cpu/softfloat3e/f16_minmax.c
new file mode 100644
index 0000000000..11922a1ba2
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_minmax.c
@@ -0,0 +1,69 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two half precision floating point numbers and return the
+| smaller of them.
+*----------------------------------------------------------------------------*/
+
+float16 f16_min(float16 a, float16 b, struct softfloat_status_t *status)
+{
+ if (softfloat_denormalsAreZeros(status)) {
+ a = f16_denormal_to_zero(a);
+ b = f16_denormal_to_zero(b);
+ }
+
+ return (f16_compare_normal(a, b, status) == softfloat_relation_less) ? a : b;
+}
+
+/*----------------------------------------------------------------------------
+| Compare between two half precision floating point numbers and return the
+| larger of them.
+*----------------------------------------------------------------------------*/
+
+float16 f16_max(float16 a, float16 b, struct softfloat_status_t *status)
+{
+ if (softfloat_denormalsAreZeros(status)) {
+ a = f16_denormal_to_zero(a);
+ b = f16_denormal_to_zero(b);
+ }
+
+ return (f16_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b;
+}
diff --git a/src/cpu/softfloat3e/f16_mul.c b/src/cpu/softfloat3e/f16_mul.c
new file mode 100644
index 0000000000..2e7e74826a
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_mul.c
@@ -0,0 +1,139 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 f16_mul(float16 a, float16 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+ bool signB;
+ int8_t expB;
+ uint16_t sigB;
+ bool signZ;
+ uint16_t magBits;
+ struct exp8_sig16 normExpSig;
+ int8_t expZ;
+ uint32_t sig32Z;
+ uint16_t sigZ, uiZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF16UI(a);
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+ signB = signF16UI(b);
+ expB = expF16UI(b);
+ sigB = fracF16UI(b);
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x1F) {
+ if (sigA || ((expB == 0x1F) && sigB)) goto propagateNaN;
+ magBits = expB | sigB;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infArg;
+ }
+ if (expB == 0x1F) {
+ if (sigB) goto propagateNaN;
+ magBits = expA | sigA;
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infArg;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! sigB) {
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA + expB - 0xF;
+ sigA = (sigA | 0x0400)<<4;
+ sigB = (sigB | 0x0400)<<5;
+ sig32Z = (uint32_t) sigA * sigB;
+ sigZ = sig32Z>>16;
+ if (sig32Z & 0xFFFF) sigZ |= 1;
+ if (sigZ < 0x4000) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ return softfloat_roundPackToF16(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF16UI(a, b, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infArg:
+ if (! magBits) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ = defaultNaNF16UI;
+ } else {
+ uiZ = packToF16UI(signZ, 0x1F, 0);
+ }
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ return packToF16UI(signZ, 0, 0);
+}
diff --git a/src/cpu/softfloat3e/f16_mulAdd.c b/src/cpu/softfloat3e/f16_mulAdd.c
new file mode 100644
index 0000000000..0e630a9b7c
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_mulAdd.c
@@ -0,0 +1,232 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+#include "specialize.h"
+
+float16 f16_mulAdd(float16 a, float16 b, float16 c, uint8_t op, struct softfloat_status_t *status)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+ bool signB;
+ int8_t expB;
+ uint16_t sigB;
+ bool signC;
+ int8_t expC;
+ uint16_t sigC;
+ bool signProd;
+ uint16_t magBits, uiA, uiB, uiC, uiZ;
+ struct exp8_sig16 normExpSig;
+ int8_t expProd;
+ uint32_t sigProd;
+ bool signZ;
+ int8_t expZ;
+ uint16_t sigZ;
+ int8_t expDiff;
+ uint32_t sig32Z, sig32C;
+ int8_t shiftDist;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA = a;
+ uiB = b;
+ uiC = c;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF16UI(uiA);
+ expA = expF16UI(uiA);
+ sigA = fracF16UI(uiA);
+ signB = signF16UI(uiB);
+ expB = expF16UI(uiB);
+ sigB = fracF16UI(uiB);
+ signC = signF16UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0);
+ expC = expF16UI(uiC);
+ sigC = fracF16UI(uiC);
+ signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ bool aisNaN = (expA == 0x1F) && sigA;
+ bool bisNaN = (expB == 0x1F) && sigB;
+ bool cisNaN = (expC == 0x1F) && sigC;
+ if (aisNaN | bisNaN | cisNaN) {
+ uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF16UI(uiA, uiB, status) : 0;
+ return softfloat_propagateNaNF16UI(uiZ, uiC, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ if (!expC) sigC = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x1F) {
+ magBits = expB | sigB;
+ goto infProdArg;
+ }
+ if (expB == 0x1F) {
+ magBits = expA | sigA;
+ goto infProdArg;
+ }
+ if (expC == 0x1F) {
+ if ((sigA && !expA) || (sigB && !expB)) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ return packToF16UI(signC, 0x1F, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! sigB) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expProd = expA + expB - 0xE;
+ sigA = (sigA | 0x0400)<<4;
+ sigB = (sigB | 0x0400)<<4;
+ sigProd = (uint32_t) sigA * sigB;
+ if (sigProd < 0x20000000) {
+ --expProd;
+ sigProd <<= 1;
+ }
+ signZ = signProd;
+ if (! expC) {
+ if (! sigC) {
+ expZ = expProd - 1;
+ sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0);
+ goto roundPack;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigC);
+ expC = normExpSig.exp;
+ sigC = normExpSig.sig;
+ }
+ sigC = (sigC | 0x0400)<<3;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expProd - expC;
+ if (signProd == signC) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff <= 0) {
+ expZ = expC;
+ sigZ = sigC + softfloat_shiftRightJam32(sigProd, 16 - expDiff);
+ } else {
+ expZ = expProd;
+ sig32Z = sigProd + softfloat_shiftRightJam32((uint32_t) sigC<<16, expDiff);
+ sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0);
+ }
+ if (sigZ < 0x4000) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sig32C = (uint32_t) sigC<<16;
+ if (expDiff < 0) {
+ signZ = signC;
+ expZ = expC;
+ sig32Z = sig32C - softfloat_shiftRightJam32(sigProd, -expDiff);
+ } else if (! expDiff) {
+ expZ = expProd;
+ sig32Z = sigProd - sig32C;
+ if (! sig32Z) goto completeCancellation;
+ if (sig32Z & 0x80000000) {
+ signZ = ! signZ;
+ sig32Z = -sig32Z;
+ }
+ } else {
+ expZ = expProd;
+ sig32Z = sigProd - softfloat_shiftRightJam32(sig32C, expDiff);
+ }
+ shiftDist = softfloat_countLeadingZeros32(sig32Z) - 1;
+ expZ -= shiftDist;
+ shiftDist -= 16;
+ if (shiftDist < 0) {
+ sigZ = sig32Z>>(-shiftDist) | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0);
+ } else {
+ sigZ = (uint16_t) sig32Z<
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 f16_range(float16 a, float16 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+ bool signB;
+ int8_t expB;
+ uint16_t sigB;
+ bool aIsNaN, bIsNaN;
+ uint16_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF16UI(a);
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+ signB = signF16UI(b);
+ expB = expF16UI(b);
+ sigB = fracF16UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_isSigNaNF16UI(a)) {
+ return softfloat_propagateNaNF16UI(a, 0, status);
+ }
+ if (softfloat_isSigNaNF16UI(b)) {
+ return softfloat_propagateNaNF16UI(b, 0, status);
+ }
+
+ aIsNaN = isNaNF16UI(a);
+ bIsNaN = isNaNF16UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA && sigA) {
+ if (softfloat_denormalsAreZeros(status)) {
+ a = packToF16UI(signA, 0, 0);
+ }
+ else if (! bIsNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ }
+
+ if (! expB && sigB) {
+ if (softfloat_denormalsAreZeros(status)) {
+ b = packToF16UI(signB, 0, 0);
+ }
+ else if (! aIsNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (bIsNaN) {
+ z = a;
+ }
+ else if (aIsNaN) {
+ z = b;
+ }
+ else if (signA != signB && ! is_abs) {
+ if (! is_max) {
+ z = signA ? a : b;
+ } else {
+ z = signA ? b : a;
+ }
+ } else {
+ float16 tmp_a = a, tmp_b = b;
+ if (is_abs) {
+ tmp_a = tmp_a & ~0x8000; // clear the sign bit
+ tmp_b = tmp_b & ~0x8000;
+ signA = 0;
+ }
+
+ if (! is_max) {
+ z = (signA ^ (tmp_a < tmp_b)) ? a : b;
+ } else {
+ z = (signA ^ (tmp_a < tmp_b)) ? b : a;
+ }
+ }
+
+ switch(sign_ctrl) {
+ case 0:
+ z = (z & ~0x8000) | (a & 0x8000); // keep sign of a
+ break;
+ case 1:
+ break; // preserve sign of compare result
+ case 2:
+ z = z & ~0x8000; // zero out the sign bit
+ break;
+ case 3:
+ z = z | 0x8000; // set the sign bit
+ break;
+ }
+
+ return z;
+}
diff --git a/src/cpu/softfloat3e/f16_roundToInt.c b/src/cpu/softfloat3e/f16_roundToInt.c
new file mode 100644
index 0000000000..ee9be0c0b3
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_roundToInt.c
@@ -0,0 +1,112 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 f16_roundToInt(float16 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ int8_t exp;
+ uint16_t frac;
+ bool sign;
+ uint16_t uiZ, lastBitMask, roundBitsMask;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ scale &= 0xF;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ sign = signF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (0x19 <= (exp + scale)) {
+ if ((exp == 0x1F) && frac) {
+ return softfloat_propagateNaNF16UI(a, 0, status);
+ }
+ return a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!exp) {
+ frac = 0;
+ a = packToF16UI(sign, 0, 0);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((exp + scale) <= 0xE) {
+ if (!(exp | frac)) return a;
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ uiZ = packToF16UI(sign, 0, 0);
+ switch (roundingMode) {
+ case softfloat_round_near_even:
+ if (!frac) break;
+ case softfloat_round_near_maxMag:
+ if ((exp + scale) == 0xE) uiZ |= packToF16UI(0, 0xF - scale, 0);
+ break;
+ case softfloat_round_min:
+ if (uiZ) uiZ = packToF16UI(1, 0xF - scale, 0);
+ break;
+ case softfloat_round_max:
+ if (!uiZ) uiZ = packToF16UI(0, 0xF - scale, 0);
+ break;
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ = a;
+ lastBitMask = (uint16_t) 1<<(0x19 - exp - scale);
+ roundBitsMask = lastBitMask - 1;
+ if (roundingMode == softfloat_round_near_maxMag) {
+ uiZ += lastBitMask>>1;
+ } else if (roundingMode == softfloat_round_near_even) {
+ uiZ += lastBitMask>>1;
+ if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask;
+ } else if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) {
+ uiZ += roundBitsMask;
+ }
+ uiZ &= ~roundBitsMask;
+ if (uiZ != a) {
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f16_sqrt.c b/src/cpu/softfloat3e/f16_sqrt.c
new file mode 100644
index 0000000000..f0f8afef19
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_sqrt.c
@@ -0,0 +1,130 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
+extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
+
+float16 f16_sqrt(float16 a, struct softfloat_status_t *status)
+{
+ bool signA;
+ int8_t expA;
+ uint16_t sigA;
+ struct exp8_sig16 normExpSig;
+ int8_t expZ;
+ int index;
+ uint16_t r0;
+ uint32_t ESqrR0;
+ uint16_t sigma0;
+ uint16_t recipSqrt16, sigZ, shiftedSigZ;
+ uint16_t negRem;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF16UI(a);
+ expA = expF16UI(a);
+ sigA = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x1F) {
+ if (sigA) {
+ return softfloat_propagateNaNF16UI(a, 0, status);
+ }
+ if (! signA) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) {
+ sigA = 0;
+ a = packToF16UI(signA, 0, 0);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (signA) {
+ if (! (expA | sigA)) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = ((expA - 0xF)>>1) + 0xE;
+ expA &= 1;
+ sigA |= 0x0400;
+ index = (sigA>>6 & 0xE) + expA;
+ r0 = softfloat_approxRecipSqrt_1k0s[index]
+ - (((uint32_t) softfloat_approxRecipSqrt_1k1s[index] * (sigA & 0x7F)) >>11);
+ ESqrR0 = ((uint32_t) r0 * r0)>>1;
+ if (expA) ESqrR0 >>= 1;
+ sigma0 = ~(uint16_t) ((ESqrR0 * sigA)>>16);
+ recipSqrt16 = r0 + (((uint32_t) r0 * sigma0)>>25);
+ if (! (recipSqrt16 & 0x8000)) recipSqrt16 = 0x8000;
+ sigZ = ((uint32_t) (sigA<<5) * recipSqrt16)>>16;
+ if (expA) sigZ >>= 1;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ ++sigZ;
+ if (! (sigZ & 7)) {
+ shiftedSigZ = sigZ>>1;
+ negRem = shiftedSigZ * shiftedSigZ;
+ sigZ &= ~1;
+ if (negRem & 0x8000) {
+ sigZ |= 1;
+ } else {
+ if (negRem) --sigZ;
+ }
+ }
+ return softfloat_roundPackToF16(0, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF16UI;
+}
diff --git a/src/cpu/softfloat3e/f16_to_extF80.cc b/src/cpu/softfloat3e/f16_to_extF80.cc
new file mode 100644
index 0000000000..418be8083d
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_extF80.cc
@@ -0,0 +1,88 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t f16_to_extF80(float16 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ uint16_t uiZ64;
+ uint64_t uiZ0;
+ struct exp8_sig16 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ if (frac) {
+ softfloat_f16UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToExtF80UI(&commonNaN);
+ uiZ64 = uiZ.v64;
+ uiZ0 = uiZ.v0;
+ } else {
+ uiZ64 = packToExtF80UI64(sign, 0x7FFF);
+ uiZ0 = UINT64_C(0x8000000000000000);
+ }
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac) {
+ return packToExtF80(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(frac);
+ exp = normExpSig.exp;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ64 = packToExtF80UI64(sign, exp + 0x3FF0);
+ uiZ0 = (uint64_t) (frac | 0x0400)<<53;
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+}
diff --git a/src/cpu/softfloat3e/f16_to_f32.c b/src/cpu/softfloat3e/f16_to_f32.c
new file mode 100644
index 0000000000..4d862161d8
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_f32.c
@@ -0,0 +1,81 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f16_to_f32(float16 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ struct commonNaN commonNaN;
+ uint32_t uiZ;
+ struct exp8_sig16 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ if (frac) {
+ softfloat_f16UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF32UI(&commonNaN);
+ } else {
+ uiZ = packToF32UI(sign, 0xFF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac || softfloat_denormalsAreZeros(status)) {
+ return packToF32UI(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(frac);
+ exp = normExpSig.exp - 1;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return packToF32UI(sign, exp + 0x70, (uint32_t) frac<<13);
+}
diff --git a/src/cpu/softfloat3e/f16_to_f64.c b/src/cpu/softfloat3e/f16_to_f64.c
new file mode 100644
index 0000000000..7d61b63577
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_f64.c
@@ -0,0 +1,81 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f16_to_f64(float16 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ struct commonNaN commonNaN;
+ uint64_t uiZ;
+ struct exp8_sig16 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ if (frac) {
+ softfloat_f16UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF64UI(&commonNaN);
+ } else {
+ uiZ = packToF64UI(sign, 0x7FF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac || softfloat_denormalsAreZeros(status)) {
+ return packToF64UI(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF16Sig(frac);
+ exp = normExpSig.exp - 1;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return packToF64UI(sign, exp + 0x3F0, (uint64_t) frac<<42);
+}
diff --git a/src/cpu/softfloat3e/f16_to_i32.c b/src/cpu/softfloat3e/f16_to_i32.c
new file mode 100644
index 0000000000..d00cfe2360
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_i32.c
@@ -0,0 +1,81 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f16_to_i32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ int32_t sig32;
+ int8_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ frac ? i32_fromNaN
+ : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig32 = frac;
+ if (exp) {
+ sig32 |= 0x0400;
+ shiftDist = exp - 0x19;
+ if (0 <= shiftDist) {
+ sig32 <<= shiftDist;
+ return sign ? -sig32 : sig32;
+ }
+ shiftDist = exp - 0x0D;
+ if (0 < shiftDist) sig32 <<= shiftDist;
+ }
+ else {
+ if (softfloat_denormalsAreZeros(status)) sig32 = 0;
+ }
+ return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status);
+}
+
diff --git a/src/cpu/softfloat3e/f16_to_i32_r_minMag.c b/src/cpu/softfloat3e/f16_to_i32_r_minMag.c
new file mode 100644
index 0000000000..9a6bbdf83b
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_i32_r_minMag.c
@@ -0,0 +1,82 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f16_to_i32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
+{
+ int8_t exp;
+ uint16_t frac;
+ int8_t shiftDist;
+ bool sign;
+ int32_t alignedSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && frac) frac = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = exp - 0x0F;
+ if (shiftDist < 0) {
+ if (exact && (exp | frac)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ if (exp == 0x1F) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x1F) && frac
+ ? i32_fromNaN
+ : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ alignedSig = (int32_t) (frac | 0x0400)<>= 10;
+ return sign ? -alignedSig : alignedSig;
+}
diff --git a/src/cpu/softfloat3e/f16_to_i64.c b/src/cpu/softfloat3e/f16_to_i64.c
new file mode 100644
index 0000000000..7dcbeaad80
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_i64.c
@@ -0,0 +1,80 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f16_to_i64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ int32_t sig32;
+ int8_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ frac ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig32 = frac;
+ if (exp) {
+ sig32 |= 0x0400;
+ shiftDist = exp - 0x19;
+ if (0 <= shiftDist) {
+ sig32 <<= shiftDist;
+ return sign ? -sig32 : sig32;
+ }
+ shiftDist = exp - 0x0D;
+ if (0 < shiftDist) sig32 <<= shiftDist;
+ }
+ else {
+ if (softfloat_denormalsAreZeros(status)) sig32 = 0;
+ }
+ return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f16_to_i64_r_minMag.c b/src/cpu/softfloat3e/f16_to_i64_r_minMag.c
new file mode 100644
index 0000000000..4289c53525
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_i64_r_minMag.c
@@ -0,0 +1,82 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f16_to_i64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
+{
+ int8_t exp;
+ uint16_t frac;
+ int8_t shiftDist;
+ bool sign;
+ int32_t alignedSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && frac) frac = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = exp - 0x0F;
+ if (shiftDist < 0) {
+ if (exact && (exp | frac)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ if (exp == 0x1F) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x1F) && frac
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ alignedSig = (int32_t) (frac | 0x0400)<>= 10;
+ return sign ? -alignedSig : alignedSig;
+}
diff --git a/src/cpu/softfloat3e/f16_to_ui32.c b/src/cpu/softfloat3e/f16_to_ui32.c
new file mode 100644
index 0000000000..d217b2627f
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_ui32.c
@@ -0,0 +1,79 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f16_to_ui32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ uint32_t sig32;
+ int8_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ frac ? ui32_fromNaN
+ : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig32 = frac;
+ if (exp) {
+ sig32 |= 0x0400;
+ shiftDist = exp - 0x19;
+ if ((0 <= shiftDist) && ! sign) {
+ return sig32<
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f16_to_ui32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
+{
+ int8_t exp;
+ uint16_t frac;
+ int8_t shiftDist;
+ bool sign;
+ uint32_t alignedSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && frac) frac = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = exp - 0x0F;
+ if (shiftDist < 0) {
+ if (exact && (exp | frac)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ if (sign || (exp == 0x1F)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x1F) && frac
+ ? ui32_fromNaN
+ : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ alignedSig = (uint32_t) (frac | 0x0400)<>10;
+}
diff --git a/src/cpu/softfloat3e/f16_to_ui64.c b/src/cpu/softfloat3e/f16_to_ui64.c
new file mode 100644
index 0000000000..351edb32ce
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_ui64.c
@@ -0,0 +1,79 @@
+/*============================================================================
+
+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, 2018 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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f16_to_ui64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int8_t exp;
+ uint16_t frac;
+ uint32_t sig32;
+ int8_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x1F) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ frac ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig32 = frac;
+ if (exp) {
+ sig32 |= 0x0400;
+ shiftDist = exp - 0x19;
+ if ((0 <= shiftDist) && ! sign) {
+ return sig32<>12, (uint64_t) sig32<<52, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c
new file mode 100644
index 0000000000..d80d6e8f5d
--- /dev/null
+++ b/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c
@@ -0,0 +1,81 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f16_to_ui64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
+{
+ int8_t exp;
+ uint16_t frac;
+ int8_t shiftDist;
+ bool sign;
+ uint32_t alignedSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF16UI(a);
+ frac = fracF16UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && frac) frac = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = exp - 0x0F;
+ if (shiftDist < 0) {
+ if (exact && (exp | frac)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF16UI(a);
+ if (sign || (exp == 0x1F)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x1F) && frac
+ ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ alignedSig = (uint32_t) (frac | 0x0400)<>10;
+}
diff --git a/src/cpu/softfloat/f2xm1.cc b/src/cpu/softfloat3e/f2xm1.cc
similarity index 77%
rename from src/cpu/softfloat/f2xm1.cc
rename to src/cpu/softfloat3e/f2xm1.cc
index ed4af1d125..16daec1d36 100644
--- a/src/cpu/softfloat/f2xm1.cc
+++ b/src/cpu/softfloat3e/f2xm1.cc
@@ -25,12 +25,15 @@ these four paragraphs for those parts of this code that are retained.
#define FLOAT128
-#include "softfloatx80.h"
-#include "softfloat-round-pack.h"
+#include "config.h"
+#include "specialize.h"
+
+#include "fpu_trans.h"
+#include "softfloat-helpers.h"
static const floatx80 floatx80_negone = packFloatx80(1, 0x3fff, BX_CONST64(0x8000000000000000));
static const floatx80 floatx80_neghalf = packFloatx80(1, 0x3ffe, BX_CONST64(0x8000000000000000));
-static const float128 float128_ln2 =
+static const float128_t float128_ln2 =
packFloat128(BX_CONST64(0x3ffe62e42fefa39e), BX_CONST64(0xf35793c7673007e6));
#ifdef BETTER_THAN_PENTIUM
@@ -47,7 +50,7 @@ static const float128 float128_ln2 =
#define EXP_ARR_SIZE 15
-static float128 exp_arr[EXP_ARR_SIZE] =
+static float128_t exp_arr[EXP_ARR_SIZE] =
{
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */
@@ -66,10 +69,10 @@ static float128 exp_arr[EXP_ARR_SIZE] =
PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */
};
-extern float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status);
+extern float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status);
/* required -1 < x < 1 */
-static float128 poly_exp(float128 x, struct float_status_t *status)
+static float128_t poly_exp(float128_t x, struct softfloat_status_t *status)
{
/*
// 2 3 4 5 6 7 8 9
@@ -92,8 +95,8 @@ static float128 poly_exp(float128 x, struct float_status_t *status)
// e - 1 ~ x * [ p(x) + x * q(x) ]
//
*/
- float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE, status);
- return float128_mul(t, x, status);
+ float128_t t = EvalPoly(x, (const float128_t*) exp_arr, EXP_ARR_SIZE, status);
+ return f128_mul(t, x, status);
}
// =================================================
@@ -114,49 +117,51 @@ static float128 poly_exp(float128 x, struct float_status_t *status)
// e = 1 + --- + --- + --- + --- + --- + ... + --- + ...
// 1! 2! 3! 4! 5! n!
//
-
-floatx80 f2xm1(floatx80 a, struct float_status_t *status)
+floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
- Bit64u zSig0, zSig1, zSig2;
+ static const floatx80 floatx80_default_nan =
+ packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+
+ uint64_t zSig0, zSig1, zSig2;
+ struct exp32_sig64 normExpSig;
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a))
- {
- float_raise(status, float_flag_invalid);
+ if (extF80_isUnsupported(a)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
return floatx80_default_nan;
}
- Bit64u aSig = extractFloatx80Frac(a);
- Bit32s aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
+ uint64_t aSig = extF80_fraction(a);
+ int32_t aExp = extF80_exp(a);
+ int aSign = extF80_sign(a);
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1))
- return propagateFloatx80NaNOne(a, status);
+ if (aSig << 1)
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, 0, 0, status);
return (aSign) ? floatx80_negone : a;
}
- if (aExp == 0) {
- if (aSig == 0) return a;
- float_raise(status, float_flag_denormal | float_flag_inexact);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ if (! aExp) {
+ if (! aSig) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal | softfloat_flag_inexact);
+ normExpSig = softfloat_normSubnormalExtF80Sig(aSig);
+ aExp = normExpSig.exp + 1;
+ aSig = normExpSig.sig;
tiny_argument:
mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2);
- if (0 < (Bit64s) zSig0) {
+ if (0 < (int64_t) zSig0) {
shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
--aExp;
}
- return
- roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1, status);
+ return softfloat_roundPackToExtF80(aSign, aExp, zSig0, zSig1, 80, status);
}
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
if (aExp < 0x3FFF)
{
@@ -167,14 +172,14 @@ floatx80 f2xm1(floatx80 a, struct float_status_t *status)
/* using float128 for approximation */
/* ******************************** */
- float128 x = floatx80_to_float128(a, status);
- x = float128_mul(x, float128_ln2, status);
+ float128_t x = extF80_to_f128(a, status);
+ x = f128_mul(x, float128_ln2, status);
x = poly_exp(x, status);
- return float128_to_floatx80(x, status);
+ return f128_to_extF80(x, status);
}
else
{
- if (a.exp == 0xBFFF && ! (aSig<<1))
+ if (a.signExp == 0xBFFF && ! (aSig<<1))
return floatx80_neghalf;
return a;
diff --git a/src/cpu/softfloat3e/f32_addsub.c b/src/cpu/softfloat3e/f32_addsub.c
new file mode 100644
index 0000000000..0b12d0e76a
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_addsub.c
@@ -0,0 +1,60 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+extern float32 softfloat_addMagsF32(uint32_t, uint32_t, struct softfloat_status_t *);
+extern float32 softfloat_subMagsF32(uint32_t, uint32_t, struct softfloat_status_t *);
+
+float32 f32_add(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ if (signF32UI((uint32_t) a ^ (uint32_t) b)) {
+ return softfloat_subMagsF32(a, b, status);
+ } else {
+ return softfloat_addMagsF32(a, b, status);
+ }
+}
+
+float32 f32_sub(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ if (signF32UI((uint32_t) a ^ (uint32_t) b)) {
+ return softfloat_addMagsF32(a, b, status);
+ } else {
+ return softfloat_subMagsF32(a, b, status);
+ }
+}
diff --git a/src/cpu/softfloat3e/f32_class.c b/src/cpu/softfloat3e/f32_class.c
new file mode 100644
index 0000000000..84c337d0e8
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_class.c
@@ -0,0 +1,64 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+softfloat_class_t f32_class(float32 a)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+
+ if (expA == 0xFF) {
+ if (sigA == 0)
+ return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
+
+ return (sigA & 0x00400000) ? softfloat_QNaN : softfloat_SNaN;
+ }
+
+ if (expA == 0) {
+ if (sigA == 0) return softfloat_zero;
+ return softfloat_denormal;
+ }
+
+ return softfloat_normalized;
+}
diff --git a/src/cpu/softfloat3e/f32_compare.c b/src/cpu/softfloat3e/f32_compare.c
new file mode 100644
index 0000000000..6c8ecfaaec
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_compare.c
@@ -0,0 +1,92 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two single precision floating point numbers. Returns
+| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
+| the value 'a' is less than the corresponding value `b',
+| 'float_relation_greater' if the value 'a' is greater than the corresponding
+| value `b', or 'float_relation_unordered' otherwise.
+*----------------------------------------------------------------------------*/
+
+int f32_compare(float32 a, float32 b, bool quiet, struct softfloat_status_t *status)
+{
+ softfloat_class_t aClass;
+ softfloat_class_t bClass;
+ bool signA;
+ bool signB;
+
+ aClass = f32_class(a);
+ bClass = f32_class(b);
+
+ if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
+ if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_denormal) {
+ if (softfloat_denormalsAreZeros(status))
+ a = a & 0x80000000;
+ else
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+
+ if (bClass == softfloat_denormal) {
+ if (softfloat_denormalsAreZeros(status))
+ b = b & 0x80000000;
+ else
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+
+ if ((a == b) || ((uint32_t) ((a | b)<<1) == 0)) return softfloat_relation_equal;
+
+ signA = signF32UI(a);
+ signB = signF32UI(b);
+ if (signA != signB)
+ return (signA) ? softfloat_relation_less : softfloat_relation_greater;
+
+ if (signA ^ (a < b)) return softfloat_relation_less;
+ return softfloat_relation_greater;
+}
diff --git a/src/cpu/softfloat3e/f32_div.c b/src/cpu/softfloat3e/f32_div.c
new file mode 100644
index 0000000000..a9ccfcfd4a
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_div.c
@@ -0,0 +1,146 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+#define SOFTFLOAT_FAST_DIV64TO32
+
+float32 f32_div(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ bool signB;
+ int16_t expB;
+ uint32_t sigB;
+ bool signZ;
+ struct exp16_sig32 normExpSig;
+ int16_t expZ;
+#ifdef SOFTFLOAT_FAST_DIV64TO32
+ uint64_t sig64A;
+ uint32_t sigZ;
+#endif
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+ signB = signF32UI(b);
+ expB = expF32UI(b);
+ sigB = fracF32UI(b);
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0xFF) {
+ if (sigA) goto propagateNaN;
+ if (expB == 0xFF) {
+ if (sigB) goto propagateNaN;
+ goto invalid;
+ }
+ if (sigB && !expB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infinity;
+ }
+ if (expB == 0xFF) {
+ if (sigB) goto propagateNaN;
+ if (sigA && !expA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expB) {
+ if (! sigB) {
+ if (! (expA | sigA)) goto invalid;
+ softfloat_raiseFlags(status, softfloat_flag_infinite);
+ goto infinity;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ if (! expA) {
+ if (! sigA) goto zero;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA - expB + 0x7E;
+ sigA |= 0x00800000;
+ sigB |= 0x00800000;
+#ifdef SOFTFLOAT_FAST_DIV64TO32
+ if (sigA < sigB) {
+ --expZ;
+ sig64A = (uint64_t) sigA<<31;
+ } else {
+ sig64A = (uint64_t) sigA<<30;
+ }
+ sigZ = sig64A / sigB;
+ if (! (sigZ & 0x3F)) sigZ |= ((uint64_t) sigB * sigZ != sig64A);
+#endif
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF32UI(a, b, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infinity:
+ return packToF32UI(signZ, 0xFF, 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ return packToF32UI(signZ, 0, 0);
+}
diff --git a/src/cpu/softfloat3e/f32_frc.c b/src/cpu/softfloat3e/f32_frc.c
new file mode 100644
index 0000000000..fc1b024603
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_frc.c
@@ -0,0 +1,101 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the fractional portion of single-precision floating-point value `a',
+| and returns the result as a single-precision floating-point value. The
+| fractional results are precise. The operation is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float32 f32_frc(float32 a, struct softfloat_status_t *status)
+{
+ int roundingMode = softfloat_getRoundingMode(status);
+
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ uint32_t lastBitMask;
+ uint32_t roundBitsMask;
+
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+
+ if (expA == 0xFF) {
+ if (sigA) return softfloat_propagateNaNF32UI(a, 0, status);
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ }
+
+ if (expA >= 0x96) {
+ return packToF32UI(roundingMode == softfloat_round_down, 0, 0);
+ }
+
+ if (expA < 0x7F) {
+ if (! expA) {
+ if (! sigA || softfloat_denormalsAreZeros(status))
+ return packToF32UI(roundingMode == softfloat_round_down, 0, 0);
+
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ if (! softfloat_isMaskedException(status, softfloat_flag_underflow))
+ softfloat_raiseFlags(status, softfloat_flag_underflow);
+
+ if (softfloat_flushUnderflowToZero(status)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
+ return packToF32UI(signA, 0, 0);
+ }
+ }
+ return a;
+ }
+
+ lastBitMask = 1 << (0x96 - expA);
+ roundBitsMask = lastBitMask - 1;
+
+ sigA &= roundBitsMask;
+ sigA <<= 7;
+ expA--;
+
+ if (! sigA)
+ return packToF32UI(roundingMode == softfloat_round_down, 0, 0);
+
+ return softfloat_normRoundPackToF32(signA, expA, sigA, status);
+}
diff --git a/src/cpu/softfloat3e/f32_getExp.c b/src/cpu/softfloat3e/f32_getExp.c
new file mode 100644
index 0000000000..66b00ac7c5
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_getExp.c
@@ -0,0 +1,73 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the exponent portion of single-precision floating-point value 'a',
+| and returns the result as a single-precision floating-point value
+| representing unbiased integer exponent. The operation is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float32 f32_getExp(float32 a, struct softfloat_status_t *status)
+{
+ int16_t expA;
+ uint32_t sigA;
+ struct exp16_sig32 normExpSig;
+
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+
+ if (expA == 0xFF) {
+ if (sigA) return softfloat_propagateNaNF32UI(a, 0, status);
+ return packToF32UI(0, 0xFF, 0);
+ }
+
+ if (! expA) {
+ if (! sigA || softfloat_denormalsAreZeros(status))
+ return packToF32UI(1, 0xFF, 0);
+
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigA);
+ expA = normExpSig.exp;
+ }
+
+ return i32_to_f32((int32_t)(expA) - 0x7F, status);
+}
diff --git a/src/cpu/softfloat3e/f32_getMant.c b/src/cpu/softfloat3e/f32_getMant.c
new file mode 100644
index 0000000000..9dfa58a632
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_getMant.c
@@ -0,0 +1,108 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the mantissa of single-precision floating-point value 'a' and
+| returns the result as a single-precision floating-point after applying
+| the mantissa interval normalization and sign control. The operation is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float32 f32_getMant(float32 a, struct softfloat_status_t *status, int sign_ctrl, int interv)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ struct exp16_sig32 normExpSig;
+
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+
+ if (expA == 0xFF) {
+ if (sigA) return softfloat_propagateNaNF32UI(a, 0, status);
+ if (signA) {
+ if (sign_ctrl & 0x2) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ }
+ }
+ return packToF32UI(~sign_ctrl & signA, 0x7F, 0);
+ }
+
+ if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) {
+ return packToF32UI(~sign_ctrl & signA, 0x7F, 0);
+ }
+
+ if (signA) {
+ if (sign_ctrl & 0x2) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ }
+ }
+
+ if (! expA) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ sigA &= 0x7FFFFF;
+ }
+
+ switch(interv) {
+ case 0x0: // interval [1,2)
+ expA = 0x7F;
+ break;
+ case 0x1: // interval [1/2,2)
+ expA -= 0x7F;
+ expA = 0x7F - (expA & 0x1);
+ break;
+ case 0x2: // interval [1/2,1)
+ expA = 0x7E;
+ break;
+ case 0x3: // interval [3/4,3/2)
+ expA = 0x7F - ((sigA >> 22) & 0x1);
+ break;
+ }
+
+ return packToF32UI(~sign_ctrl & signA, expA, sigA);
+}
diff --git a/src/cpu/softfloat3e/f32_minmax.c b/src/cpu/softfloat3e/f32_minmax.c
new file mode 100644
index 0000000000..e36c297ae7
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_minmax.c
@@ -0,0 +1,69 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two single precision floating point numbers and return the
+| smaller of them.
+*----------------------------------------------------------------------------*/
+
+float32 f32_min(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ if (softfloat_denormalsAreZeros(status)) {
+ a = f32_denormal_to_zero(a);
+ b = f32_denormal_to_zero(b);
+ }
+
+ return (f32_compare_normal(a, b, status) == softfloat_relation_less) ? a : b;
+}
+
+/*----------------------------------------------------------------------------
+| Compare between two single precision floating point numbers and return the
+| larger of them.
+*----------------------------------------------------------------------------*/
+
+float32 f32_max(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ if (softfloat_denormalsAreZeros(status)) {
+ a = f32_denormal_to_zero(a);
+ b = f32_denormal_to_zero(b);
+ }
+
+ return (f32_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b;
+}
diff --git a/src/cpu/softfloat3e/f32_mul.c b/src/cpu/softfloat3e/f32_mul.c
new file mode 100644
index 0000000000..db96e0db7a
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_mul.c
@@ -0,0 +1,137 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f32_mul(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ bool signB;
+ int16_t expB;
+ uint32_t sigB;
+ bool signZ;
+ uint32_t magBits;
+ struct exp16_sig32 normExpSig;
+ int16_t expZ;
+ uint32_t sigZ, uiZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+ signB = signF32UI(b);
+ expB = expF32UI(b);
+ sigB = fracF32UI(b);
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0xFF) {
+ if (sigA || ((expB == 0xFF) && sigB)) goto propagateNaN;
+ magBits = expB | sigB;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infArg;
+ }
+ if (expB == 0xFF) {
+ if (sigB) goto propagateNaN;
+ magBits = expA | sigA;
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infArg;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! sigB) {
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA + expB - 0x7F;
+ sigA = (sigA | 0x00800000)<<7;
+ sigB = (sigB | 0x00800000)<<8;
+ sigZ = softfloat_shortShiftRightJam64((uint64_t) sigA * sigB, 32);
+ if (sigZ < 0x40000000) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF32UI(a, b, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infArg:
+ if (! magBits) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ = defaultNaNF32UI;
+ } else {
+ uiZ = packToF32UI(signZ, 0xFF, 0);
+ }
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ return packToF32UI(signZ, 0, 0);
+}
diff --git a/src/cpu/softfloat3e/f32_mulAdd.c b/src/cpu/softfloat3e/f32_mulAdd.c
new file mode 100644
index 0000000000..101b20f18b
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_mulAdd.c
@@ -0,0 +1,233 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+#include "specialize.h"
+
+float32 f32_mulAdd(float32 a, float32 b, float32 c, uint8_t op, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ bool signB;
+ int16_t expB;
+ uint32_t sigB;
+ bool signC;
+ int16_t expC;
+ uint32_t sigC;
+ bool signProd;
+ uint32_t magBits, uiA, uiB, uiC, uiZ;
+ struct exp16_sig32 normExpSig;
+ int16_t expProd;
+ uint64_t sigProd;
+ bool signZ;
+ int16_t expZ;
+ uint32_t sigZ;
+ int16_t expDiff;
+ uint64_t sig64Z, sig64C;
+ int8_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA = a;
+ uiB = b;
+ uiC = c;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF32UI(uiA);
+ expA = expF32UI(uiA);
+ sigA = fracF32UI(uiA);
+ signB = signF32UI(uiB);
+ expB = expF32UI(uiB);
+ sigB = fracF32UI(uiB);
+ signC = signF32UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0);
+ expC = expF32UI(uiC);
+ sigC = fracF32UI(uiC);
+ signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ bool aisNaN = (expA == 0xFF) && sigA;
+ bool bisNaN = (expB == 0xFF) && sigB;
+ bool cisNaN = (expC == 0xFF) && sigC;
+ if (aisNaN | bisNaN | cisNaN) {
+ uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF32UI(uiA, uiB, status) : 0;
+ return softfloat_propagateNaNF32UI(uiZ, uiC, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ if (!expC) sigC = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0xFF) {
+ magBits = expB | sigB;
+ goto infProdArg;
+ }
+ if (expB == 0xFF) {
+ magBits = expA | sigA;
+ goto infProdArg;
+ }
+ if (expC == 0xFF) {
+ if ((sigA && !expA) || (sigB && !expB)) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ return packToF32UI(signC, 0xFF, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! sigB) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expProd = expA + expB - 0x7E;
+ sigA = (sigA | 0x00800000)<<7;
+ sigB = (sigB | 0x00800000)<<7;
+ sigProd = (uint64_t) sigA * sigB;
+ if (sigProd < UINT64_C(0x2000000000000000)) {
+ --expProd;
+ sigProd <<= 1;
+ }
+ signZ = signProd;
+ if (! expC) {
+ if (! sigC) {
+ expZ = expProd - 1;
+ sigZ = softfloat_shortShiftRightJam64(sigProd, 31);
+ goto roundPack;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigC);
+ expC = normExpSig.exp;
+ sigC = normExpSig.sig;
+ }
+ sigC = (sigC | 0x00800000)<<6;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expProd - expC;
+ if (signProd == signC) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff <= 0) {
+ expZ = expC;
+ sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff);
+ } else {
+ expZ = expProd;
+ sig64Z = sigProd + softfloat_shiftRightJam64((uint64_t) sigC<<32, expDiff);
+ sigZ = softfloat_shortShiftRightJam64(sig64Z, 32);
+ }
+ if (sigZ < 0x40000000) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sig64C = (uint64_t) sigC<<32;
+ if (expDiff < 0) {
+ signZ = signC;
+ expZ = expC;
+ sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff);
+ } else if (! expDiff) {
+ expZ = expProd;
+ sig64Z = sigProd - sig64C;
+ if (! sig64Z) goto completeCancellation;
+ if (sig64Z & UINT64_C(0x8000000000000000)) {
+ signZ = ! signZ;
+ sig64Z = -sig64Z;
+ }
+ } else {
+ expZ = expProd;
+ sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff);
+ }
+ shiftDist = softfloat_countLeadingZeros64(sig64Z) - 1;
+ expZ -= shiftDist;
+ shiftDist -= 32;
+ if (shiftDist < 0) {
+ sigZ = softfloat_shortShiftRightJam64(sig64Z, -shiftDist);
+ } else {
+ sigZ = (uint32_t) sig64Z<
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f32_range(float32 a, float32 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ bool signB;
+ int16_t expB;
+ uint32_t sigB;
+ bool aIsNaN, bIsNaN;
+ uint32_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+ signB = signF32UI(b);
+ expB = expF32UI(b);
+ sigB = fracF32UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_isSigNaNF32UI(a)) {
+ return softfloat_propagateNaNF32UI(a, 0, status);
+ }
+ if (softfloat_isSigNaNF32UI(b)) {
+ return softfloat_propagateNaNF32UI(b, 0, status);
+ }
+
+ aIsNaN = isNaNF32UI(a);
+ bIsNaN = isNaNF32UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA && sigA) {
+ if (softfloat_denormalsAreZeros(status)) {
+ a = packToF32UI(signA, 0, 0);
+ }
+ else if (! bIsNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ }
+
+ if (! expB && sigB) {
+ if (softfloat_denormalsAreZeros(status)) {
+ b = packToF32UI(signB, 0, 0);
+ }
+ else if (! aIsNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (bIsNaN) {
+ z = a;
+ }
+ else if (aIsNaN) {
+ z = b;
+ }
+ else if (signA != signB && ! is_abs) {
+ if (! is_max) {
+ z = signA ? a : b;
+ } else {
+ z = signA ? b : a;
+ }
+ } else {
+ float32 tmp_a = a, tmp_b = b;
+ if (is_abs) {
+ tmp_a = tmp_a & ~0x80000000; // clear the sign bit
+ tmp_b = tmp_b & ~0x80000000;
+ signA = 0;
+ }
+ if (! is_max) {
+ z = (signA ^ (tmp_a < tmp_b)) ? a : b;
+ } else {
+ z = (signA ^ (tmp_a < tmp_b)) ? b : a;
+ }
+ }
+
+ switch(sign_ctrl) {
+ case 0:
+ z = (z & ~0x80000000) | (a & 0x80000000); // keep sign of a
+ break;
+ case 1:
+ break; // preserve sign of compare result
+ case 2:
+ z = z & ~0x80000000; // zero out the sign bit
+ break;
+ case 3:
+ z = z | 0x80000000; // set the sign bit
+ break;
+ }
+
+ return z;
+}
diff --git a/src/cpu/softfloat3e/f32_roundToInt.c b/src/cpu/softfloat3e/f32_roundToInt.c
new file mode 100644
index 0000000000..7791fbbf41
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_roundToInt.c
@@ -0,0 +1,112 @@
+/*============================================================================
+
+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, 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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f32_roundToInt(float32 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ int32_t frac;
+ uint32_t uiZ, lastBitMask, roundBitsMask;
+ bool sign;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ scale &= 0xF;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF32UI(a);
+ frac = fracF32UI(a);
+ sign = signF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (0x96 <= (exp + scale)) {
+ if ((exp == 0xFF) && frac) {
+ return softfloat_propagateNaNF32UI(a, 0, status);
+ }
+ return a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!exp) {
+ frac = 0;
+ a = packToF32UI(sign, 0, 0);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((exp + scale) <= 0x7E) {
+ if (!(exp | frac)) return a;
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ uiZ = packToF32UI(sign, 0, 0);
+ switch (roundingMode) {
+ case softfloat_round_near_even:
+ if (!frac) break;
+ case softfloat_round_near_maxMag:
+ if ((exp + scale) == 0x7E) uiZ |= packToF32UI(0, 0x7F - scale, 0);
+ break;
+ case softfloat_round_min:
+ if (uiZ) uiZ = packToF32UI(1, 0x7F - scale, 0);
+ break;
+ case softfloat_round_max:
+ if (!uiZ) uiZ = packToF32UI(0, 0x7F - scale, 0);
+ break;
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ = a;
+ lastBitMask = (uint32_t) 1<<(0x96 - exp - scale);
+ roundBitsMask = lastBitMask - 1;
+ if (roundingMode == softfloat_round_near_maxMag) {
+ uiZ += lastBitMask>>1;
+ } else if (roundingMode == softfloat_round_near_even) {
+ uiZ += lastBitMask>>1;
+ if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask;
+ } else if (roundingMode == (signF32UI(uiZ) ? softfloat_round_min : softfloat_round_max)) {
+ uiZ += roundBitsMask;
+ }
+ uiZ &= ~roundBitsMask;
+ if (uiZ != a) {
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f32_scalef.c b/src/cpu/softfloat3e/f32_scalef.c
new file mode 100644
index 0000000000..320baff30a
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_scalef.c
@@ -0,0 +1,155 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Return the result of a floating point scale of the single-precision floating
+| point value `a' by multiplying it by 2 power of the single-precision
+| floating point value 'b' converted to integral value. If the result cannot
+| be represented in single precision, then the proper overflow response (for
+| positive scaling operand), or the proper underflow response (for negative
+| scaling operand) is issued. The operation is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float32 f32_scalef(float32 a, float32 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ bool signB;
+ int16_t expB;
+ uint32_t sigB;
+ int shiftCount;
+ int scale = 0;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+ signB = signF32UI(b);
+ expB = expF32UI(b);
+ sigB = fracF32UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expB == 0xFF) {
+ if (sigB) return softfloat_propagateNaNF32UI(a, b, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0xFF) {
+ if (sigA) {
+ int aIsSignalingNaN = (sigA & 0x00400000) == 0;
+ if (aIsSignalingNaN || expB != 0xFF || sigB)
+ return softfloat_propagateNaNF32UI(a, b, status);
+
+ return signB ? 0 : packToF32UI(0, 0xFF, 0);
+ }
+
+ if (expB == 0xFF && signB) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ }
+
+ return a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ if (expB == 0xFF && ! signB) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+ }
+ return packToF32UI(signA, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((expB | sigB) == 0) return a;
+
+ if (expB == 0xFF) {
+ if (signB) return packToF32UI(signA, 0, 0);
+ return packToF32UI(signA, 0xFF, 0);
+ }
+
+ if (expB >= 0x8E) {
+ // handle obvious overflow/underflow result
+ return softfloat_roundPackToF32(signA, signB ? -0x7F : 0xFF, sigA, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expB <= 0x7E) {
+ if (! expB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ scale = -signB;
+ }
+ else {
+ shiftCount = expB - 0x9E;
+ sigB = (sigB | 0x800000)<<8;
+ scale = sigB>>(-shiftCount);
+
+ if (signB) {
+ if ((uint32_t) (sigB<<(shiftCount & 31))) scale++;
+ scale = -scale;
+ }
+
+ if (scale > 0x200) scale = 0x200;
+ if (scale < -0x200) scale = -0x200;
+ }
+
+ if (expA != 0) {
+ sigA |= 0x00800000;
+ } else {
+ expA++;
+ }
+
+ expA += scale - 1;
+ sigA <<= 7;
+ return softfloat_normRoundPackToF32(signA, expA, sigA, status);
+}
diff --git a/src/cpu/softfloat3e/f32_sqrt.c b/src/cpu/softfloat3e/f32_sqrt.c
new file mode 100644
index 0000000000..fc2ef8f761
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_sqrt.c
@@ -0,0 +1,117 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f32_sqrt(float32 a, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint32_t sigA;
+ struct exp16_sig32 normExpSig;
+ int16_t expZ;
+ uint32_t sigZ, shiftedSigZ;
+ uint32_t negRem;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF32UI(a);
+ expA = expF32UI(a);
+ sigA = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0xFF) {
+ if (sigA) {
+ return softfloat_propagateNaNF32UI(a, 0, status);
+ }
+ if (! signA) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) {
+ sigA = 0;
+ a = packToF32UI(signA, 0, 0);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (signA) {
+ if (! (expA | sigA)) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = ((expA - 0x7F)>>1) + 0x7E;
+ expA &= 1;
+ sigA = (sigA | 0x00800000)<<8;
+ sigZ =
+ ((uint64_t) sigA * softfloat_approxRecipSqrt32_1(expA, sigA))>>32;
+ if (expA) sigZ >>= 1;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sigZ += 2;
+ if ((sigZ & 0x3F) < 2) {
+ shiftedSigZ = sigZ>>2;
+ negRem = shiftedSigZ * shiftedSigZ;
+ sigZ &= ~3;
+ if (negRem & 0x80000000) {
+ sigZ |= 1;
+ } else {
+ if (negRem) --sigZ;
+ }
+ }
+ return softfloat_roundPackToF32(0, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF32UI;
+}
diff --git a/src/cpu/softfloat3e/f32_to_extF80.cc b/src/cpu/softfloat3e/f32_to_extF80.cc
new file mode 100644
index 0000000000..73b8bedfdd
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_extF80.cc
@@ -0,0 +1,88 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t f32_to_extF80(float32 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t frac;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ uint16_t uiZ64;
+ uint64_t uiZ0;
+ struct exp16_sig32 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ frac = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0xFF) {
+ if (frac) {
+ softfloat_f32UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToExtF80UI(&commonNaN);
+ uiZ64 = uiZ.v64;
+ uiZ0 = uiZ.v0;
+ } else {
+ uiZ64 = packToExtF80UI64(sign, 0x7FFF);
+ uiZ0 = UINT64_C(0x8000000000000000);
+ }
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac) {
+ return packToExtF80(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(frac);
+ exp = normExpSig.exp;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ64 = packToExtF80UI64(sign, exp + 0x3F80);
+ uiZ0 = (uint64_t) (frac | 0x00800000)<<40;
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+}
diff --git a/src/cpu/softfloat3e/f32_to_f128.cc b/src/cpu/softfloat3e/f32_to_f128.cc
new file mode 100644
index 0000000000..6d3fafec29
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_f128.cc
@@ -0,0 +1,86 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f32_to_f128(float32 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t frac;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ struct exp16_sig32 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ frac = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0xFF) {
+ if (frac) {
+ softfloat_f32UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF128UI(&commonNaN);
+ } else {
+ uiZ.v64 = packToF128UI64(sign, 0x7FFF, 0);
+ uiZ.v0 = 0;
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac) {
+ uiZ.v64 = packToF128UI64(sign, 0, 0);
+ uiZ.v0 = 0;
+ return uiZ;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(frac);
+ exp = normExpSig.exp - 1;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ.v64 = packToF128UI64(sign, exp + 0x3F80, (uint64_t) frac<<25);
+ uiZ.v0 = 0;
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f32_to_f16.c b/src/cpu/softfloat3e/f32_to_f16.c
new file mode 100644
index 0000000000..9253a958a5
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_f16.c
@@ -0,0 +1,82 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 f32_to_f16(float32 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t frac;
+ struct commonNaN commonNaN;
+ uint16_t uiZ, frac16;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ frac = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0xFF) {
+ if (frac) {
+ softfloat_f32UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF16UI(&commonNaN);
+ } else {
+ uiZ = packToF16UI(sign, 0x1F, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (!exp && frac) {
+ if (softfloat_denormalsAreZeros(status))
+ return packToF16UI(sign, 0, 0);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac16 = frac>>9 | ((frac & 0x1FF) != 0);
+ if (! (exp | frac16)) {
+ return packToF16UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return softfloat_roundPackToF16(sign, exp - 0x71, frac16 | 0x4000, status);
+}
diff --git a/src/cpu/softfloat3e/f32_to_f64.c b/src/cpu/softfloat3e/f32_to_f64.c
new file mode 100644
index 0000000000..28ebb61b6c
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_f64.c
@@ -0,0 +1,81 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f32_to_f64(float32 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t frac;
+ struct commonNaN commonNaN;
+ uint64_t uiZ;
+ struct exp16_sig32 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ frac = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0xFF) {
+ if (frac) {
+ softfloat_f32UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF64UI(&commonNaN);
+ } else {
+ uiZ = packToF64UI(sign, 0x7FF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac || softfloat_denormalsAreZeros(status)) {
+ return packToF64UI(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF32Sig(frac);
+ exp = normExpSig.exp - 1;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return packToF64UI(sign, exp + 0x380, (uint64_t) frac<<29);
+}
diff --git a/src/cpu/softfloat3e/f32_to_i32.c b/src/cpu/softfloat3e/f32_to_i32.c
new file mode 100644
index 0000000000..2b3df52a3c
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_i32.c
@@ -0,0 +1,78 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f32_to_i32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t sig;
+ uint64_t sig64;
+ int16_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
+ if ((exp == 0xFF) && sig) {
+#if (i32_fromNaN == i32_fromPosOverflow)
+ sign = 0;
+#elif (i32_fromNaN == i32_fromNegOverflow)
+ sign = 1;
+#else
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i32_fromNaN;
+#endif
+ }
+#endif
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= 0x00800000;
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ sig64 = (uint64_t) sig<<32;
+ shiftDist = 0xAA - exp;
+ if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist);
+ return softfloat_roundToI32(sign, sig64, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f32_to_i32_r_minMag.c b/src/cpu/softfloat3e/f32_to_i32_r_minMag.c
new file mode 100644
index 0000000000..abe782d3b0
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_i32_r_minMag.c
@@ -0,0 +1,83 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f32_to_i32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint32_t sig;
+ int16_t shiftDist;
+ bool sign;
+ int32_t absZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x9E - exp;
+ if (32 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ if (shiftDist <= 0) {
+ if (a == packToF32UI(1, 0x9E, 0)) return -0x7FFFFFFF - 1;
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0xFF) && sig
+ ? i32_fromNaN
+ : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig = (sig | 0x00800000)<<8;
+ absZ = sig>>shiftDist;
+ if (exact && ((uint32_t) absZ<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f32_to_i64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t sig;
+ int16_t shiftDist;
+ uint64_t sig64, extra;
+ struct uint64_extra sig64Extra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0xBE - exp;
+ if (shiftDist < 0) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0xFF) && sig
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= 0x00800000;
+ sig64 = (uint64_t) sig<<40;
+ extra = 0;
+ if (shiftDist) {
+ sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, shiftDist);
+ sig64 = sig64Extra.v;
+ extra = sig64Extra.extra;
+ }
+ return softfloat_roundToI64(sign, sig64, extra, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f32_to_i64_r_minMag.c b/src/cpu/softfloat3e/f32_to_i64_r_minMag.c
new file mode 100644
index 0000000000..2ccabd09de
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_i64_r_minMag.c
@@ -0,0 +1,88 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f32_to_i64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint32_t sig;
+ int16_t shiftDist;
+ bool sign;
+ uint64_t sig64;
+ int64_t absZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0xBE - exp;
+ if (64 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ if (shiftDist <= 0) {
+ if (a == packToF32UI(1, 0xBE, 0)) {
+ return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0xFF) && sig
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig |= 0x00800000;
+ sig64 = (uint64_t) sig<<40;
+ absZ = sig64>>shiftDist;
+ shiftDist = 40 - shiftDist;
+ if (exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31))) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return sign ? -absZ : absZ;
+}
diff --git a/src/cpu/softfloat3e/f32_to_ui32.c b/src/cpu/softfloat3e/f32_to_ui32.c
new file mode 100644
index 0000000000..5a8d574142
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_ui32.c
@@ -0,0 +1,80 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f32_to_ui32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t sig;
+ uint64_t sig64;
+ int16_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
+ if ((exp == 0xFF) && sig) {
+#if (ui32_fromNaN == ui32_fromPosOverflow)
+ sign = 0;
+#elif (ui32_fromNaN == ui32_fromNegOverflow)
+ sign = 1;
+#else
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui32_fromNaN;
+#endif
+ }
+#endif
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= 0x00800000;
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ sig64 = (uint64_t) sig<<32;
+ shiftDist = 0xAA - exp;
+ if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist);
+ return softfloat_roundToUI32(sign, sig64, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c b/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c
new file mode 100644
index 0000000000..4b37708b04
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c
@@ -0,0 +1,83 @@
+
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f32_to_ui32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint32_t sig;
+ int16_t shiftDist;
+ bool sign;
+ uint32_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x9E - exp;
+ if (32 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ if (sign || (shiftDist < 0)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0xFF) && sig
+ ? ui32_fromNaN
+ : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig = (sig | 0x00800000)<<8;
+ z = sig>>shiftDist;
+ if (exact && (z<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f32_to_ui64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint32_t sig;
+ int16_t shiftDist;
+ uint64_t sig64, extra;
+ struct uint64_extra sig64Extra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0xBE - exp;
+ if (shiftDist < 0) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0xFF) && sig
+ ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= 0x00800000;
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ sig64 = (uint64_t) sig<<40;
+ extra = 0;
+ if (shiftDist) {
+ sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, shiftDist);
+ sig64 = sig64Extra.v;
+ extra = sig64Extra.extra;
+ }
+ return softfloat_roundToUI64(sign, sig64, extra, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c
new file mode 100644
index 0000000000..111c50e7f2
--- /dev/null
+++ b/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c
@@ -0,0 +1,84 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f32_to_ui64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint32_t sig;
+ int16_t shiftDist;
+ bool sign;
+ uint64_t sig64, z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF32UI(a);
+ sig = fracF32UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0xBE - exp;
+ if (64 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF32UI(a);
+ if (sign || (shiftDist < 0)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0xFF) && sig
+ ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig |= 0x00800000;
+ sig64 = (uint64_t) sig<<40;
+ z = sig64>>shiftDist;
+ shiftDist = 40 - shiftDist;
+ if (exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31))) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return z;
+}
diff --git a/src/cpu/softfloat3e/f64_addsub.c b/src/cpu/softfloat3e/f64_addsub.c
new file mode 100644
index 0000000000..6c5acb4f77
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_addsub.c
@@ -0,0 +1,70 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+extern float64 softfloat_addMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *);
+extern float64 softfloat_subMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *);
+
+float64 f64_add(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ bool signB;
+
+ signA = signF64UI(a);
+ signB = signF64UI(b);
+ if (signA == signB) {
+ return softfloat_addMagsF64(a, b, signA, status);
+ } else {
+ return softfloat_subMagsF64(a, b, signA, status);
+ }
+}
+
+float64 f64_sub(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ bool signB;
+
+ signA = signF64UI(a);
+ signB = signF64UI(b);
+ if (signA == signB) {
+ return softfloat_subMagsF64(a, b, signA, status);
+ } else {
+ return softfloat_addMagsF64(a, b, signA, status);
+ }
+}
diff --git a/src/cpu/softfloat3e/f64_class.c b/src/cpu/softfloat3e/f64_class.c
new file mode 100644
index 0000000000..1d44a63518
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_class.c
@@ -0,0 +1,64 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+softfloat_class_t f64_class(float64 a)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+
+ if (expA == 0x7FF) {
+ if (sigA == 0)
+ return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
+
+ return (sigA & UINT64_C(0x0008000000000000)) ? softfloat_QNaN : softfloat_SNaN;
+ }
+
+ if (expA == 0) {
+ if (sigA == 0) return softfloat_zero;
+ return softfloat_denormal;
+ }
+
+ return softfloat_normalized;
+}
diff --git a/src/cpu/softfloat3e/f64_compare.c b/src/cpu/softfloat3e/f64_compare.c
new file mode 100644
index 0000000000..aed2507682
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_compare.c
@@ -0,0 +1,92 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two double precision floating point numbers. Returns
+| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
+| the value 'a' is less than the corresponding value `b',
+| 'float_relation_greater' if the value 'a' is greater than the corresponding
+| value `b', or 'float_relation_unordered' otherwise.
+*----------------------------------------------------------------------------*/
+
+int f64_compare(float64 a, float64 b, bool quiet, struct softfloat_status_t *status)
+{
+ softfloat_class_t aClass;
+ softfloat_class_t bClass;
+ bool signA;
+ bool signB;
+
+ aClass = f64_class(a);
+ bClass = f64_class(b);
+
+ if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
+ if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return softfloat_relation_unordered;
+ }
+
+ if (aClass == softfloat_denormal) {
+ if (softfloat_denormalsAreZeros(status))
+ a = a & UINT64_C(0x8000000000000000);
+ else
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+
+ if (bClass == softfloat_denormal) {
+ if (softfloat_denormalsAreZeros(status))
+ b = b & UINT64_C(0x8000000000000000);
+ else
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+
+ if ((a == b) || ((uint64_t) ((a | b)<<1) == 0)) return softfloat_relation_equal;
+
+ signA = signF64UI(a);
+ signB = signF64UI(b);
+ if (signA != signB)
+ return (signA) ? softfloat_relation_less : softfloat_relation_greater;
+
+ if (signA ^ (a < b)) return softfloat_relation_less;
+ return softfloat_relation_greater;
+}
diff --git a/src/cpu/softfloat3e/f64_div.c b/src/cpu/softfloat3e/f64_div.c
new file mode 100644
index 0000000000..89f74f1b10
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_div.c
@@ -0,0 +1,165 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f64_div(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ bool signB;
+ int16_t expB;
+ uint64_t sigB;
+ bool signZ;
+ struct exp16_sig64 normExpSig;
+ int16_t expZ;
+ uint32_t recip32, sig32Z, doubleTerm;
+ uint64_t rem;
+ uint32_t q;
+ uint64_t sigZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+ signB = signF64UI(b);
+ expB = expF64UI(b);
+ sigB = fracF64UI(b);
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FF) {
+ if (sigA) goto propagateNaN;
+ if (expB == 0x7FF) {
+ if (sigB) goto propagateNaN;
+ goto invalid;
+ }
+ if (sigB && !expB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infinity;
+ }
+ if (expB == 0x7FF) {
+ if (sigB) goto propagateNaN;
+ if (sigA && !expA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expB) {
+ if (! sigB) {
+ if (! (expA | sigA)) goto invalid;
+ softfloat_raiseFlags(status, softfloat_flag_infinite);
+ goto infinity;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ if (! expA) {
+ if (! sigA) goto zero;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA - expB + 0x3FE;
+ sigA |= UINT64_C(0x0010000000000000);
+ sigB |= UINT64_C(0x0010000000000000);
+ if (sigA < sigB) {
+ --expZ;
+ sigA <<= 11;
+ } else {
+ sigA <<= 10;
+ }
+ sigB <<= 11;
+ recip32 = softfloat_approxRecip32_1(sigB>>32) - 2;
+ sig32Z = ((uint32_t) (sigA>>32) * (uint64_t) recip32)>>32;
+ doubleTerm = sig32Z<<1;
+ rem =
+ ((sigA - (uint64_t) doubleTerm * (uint32_t) (sigB>>32))<<28)
+ - (uint64_t) doubleTerm * ((uint32_t) sigB>>4);
+ q = (((uint32_t) (rem>>32) * (uint64_t) recip32)>>32) + 4;
+ sigZ = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<4);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((sigZ & 0x1FF) < 4<<4) {
+ q &= ~7;
+ sigZ &= ~(uint64_t) 0x7F;
+ doubleTerm = q<<1;
+ rem =
+ ((rem - (uint64_t) doubleTerm * (uint32_t) (sigB>>32))<<28)
+ - (uint64_t) doubleTerm * ((uint32_t) sigB>>4);
+ if (rem & UINT64_C(0x8000000000000000)) {
+ sigZ -= 1<<7;
+ } else {
+ if (rem) sigZ |= 1;
+ }
+ }
+ return softfloat_roundPackToF64(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF64UI(a, b, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infinity:
+ return packToF64UI(signZ, 0x7FF, 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ return packToF64UI(signZ, 0, 0);
+}
diff --git a/src/cpu/softfloat3e/f64_frc.c b/src/cpu/softfloat3e/f64_frc.c
new file mode 100644
index 0000000000..46c21ac4f8
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_frc.c
@@ -0,0 +1,101 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the fractional portion of double-precision floating-point value `a',
+| and returns the result as a double-precision floating-point value. The
+| fractional results are precise. The operation is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float64 f64_frc(float64 a, struct softfloat_status_t *status)
+{
+ int roundingMode = softfloat_getRoundingMode(status);
+
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ uint64_t lastBitMask;
+ uint64_t roundBitsMask;
+
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+
+ if (expA == 0x7FF) {
+ if (sigA) return softfloat_propagateNaNF64UI(a, 0, status);
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ }
+
+ if (expA >= 0x433) {
+ return packToF64UI(roundingMode == softfloat_round_down, 0, 0);
+ }
+
+ if (expA < 0x3FF) {
+ if (! expA) {
+ if (! sigA || softfloat_denormalsAreZeros(status))
+ return packToF64UI(roundingMode == softfloat_round_down, 0, 0);
+
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ if (! softfloat_isMaskedException(status, softfloat_flag_underflow))
+ softfloat_raiseFlags(status, softfloat_flag_underflow);
+
+ if (softfloat_flushUnderflowToZero(status)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
+ return packToF64UI(signA, 0, 0);
+ }
+ }
+ return a;
+ }
+
+ lastBitMask = UINT64_C(1) << (0x433 - expA);
+ roundBitsMask = lastBitMask - 1;
+
+ sigA &= roundBitsMask;
+ sigA <<= 10;
+ expA--;
+
+ if (! sigA)
+ return packToF64UI(roundingMode == softfloat_round_down, 0, 0);
+
+ return softfloat_normRoundPackToF64(signA, expA, sigA, status);
+}
diff --git a/src/cpu/softfloat3e/f64_getExp.c b/src/cpu/softfloat3e/f64_getExp.c
new file mode 100644
index 0000000000..b76cc996d5
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_getExp.c
@@ -0,0 +1,73 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the exponent portion of double-precision floating-point value 'a',
+| and returns the result as a double-precision floating-point value
+| representing unbiased integer exponent. The operation is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float64 f64_getExp(float64 a, struct softfloat_status_t *status)
+{
+ int16_t expA;
+ uint64_t sigA;
+ struct exp16_sig64 normExpSig;
+
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+
+ if (expA == 0x7FF) {
+ if (sigA) return softfloat_propagateNaNF64UI(a, 0, status);
+ return packToF64UI(0, 0x7FF, 0);
+ }
+
+ if (! expA) {
+ if (! sigA || softfloat_denormalsAreZeros(status))
+ return packToF64UI(1, 0x7FF, 0);
+
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigA);
+ expA = normExpSig.exp;
+ }
+
+ return i32_to_f64((int32_t)(expA) - 0x3FF);
+}
diff --git a/src/cpu/softfloat3e/f64_getMant.c b/src/cpu/softfloat3e/f64_getMant.c
new file mode 100644
index 0000000000..84077e3148
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_getMant.c
@@ -0,0 +1,108 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Extracts the mantissa of double-precision floating-point value 'a' and
+| returns the result as a double-precision floating-point after applying
+| the mantissa interval normalization and sign control. The operation is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float64 f64_getMant(float64 a, struct softfloat_status_t *status, int sign_ctrl, int interv)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ struct exp16_sig64 normExpSig;
+
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+
+ if (expA == 0x7FF) {
+ if (sigA) return softfloat_propagateNaNF64UI(a, 0, status);
+ if (signA) {
+ if (sign_ctrl & 0x2) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ }
+ }
+ return packToF64UI(~sign_ctrl & signA, 0x3FF, 0);
+ }
+
+ if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) {
+ return packToF64UI(~sign_ctrl & signA, 0x3FF, 0);
+ }
+
+ if (signA) {
+ if (sign_ctrl & 0x2) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ }
+ }
+
+ if (expA == 0) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ sigA &= UINT64_C(0xFFFFFFFFFFFFF);
+ }
+
+ switch(interv) {
+ case 0x0: // interval [1,2)
+ expA = 0x3FF;
+ break;
+ case 0x1: // interval [1/2,2)
+ expA -= 0x3FF;
+ expA = 0x3FF - (expA & 0x1);
+ break;
+ case 0x2: // interval [1/2,1)
+ expA = 0x3FE;
+ break;
+ case 0x3: // interval [3/4,3/2)
+ expA = 0x3FF - ((sigA >> 51) & 0x1);
+ break;
+ }
+
+ return packToF64UI(~sign_ctrl & signA, expA, sigA);
+}
diff --git a/src/cpu/softfloat3e/f64_minmax.c b/src/cpu/softfloat3e/f64_minmax.c
new file mode 100644
index 0000000000..3c927410ab
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_minmax.c
@@ -0,0 +1,69 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Compare between two double precision floating point numbers and return the
+| smaller of them.
+*----------------------------------------------------------------------------*/
+
+float64 f64_min(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ if (softfloat_denormalsAreZeros(status)) {
+ a = f64_denormal_to_zero(a);
+ b = f64_denormal_to_zero(b);
+ }
+
+ return (f64_compare_normal(a, b, status) == softfloat_relation_less) ? a : b;
+}
+
+/*----------------------------------------------------------------------------
+| Compare between two double precision floating point numbers and return the
+| larger of them.
+*----------------------------------------------------------------------------*/
+
+float64 f64_max(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ if (softfloat_denormalsAreZeros(status)) {
+ a = f64_denormal_to_zero(a);
+ b = f64_denormal_to_zero(b);
+ }
+
+ return (f64_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b;
+}
diff --git a/src/cpu/softfloat3e/f64_mul.c b/src/cpu/softfloat3e/f64_mul.c
new file mode 100644
index 0000000000..c1e98f2b6d
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_mul.c
@@ -0,0 +1,139 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f64_mul(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ bool signB;
+ int16_t expB;
+ uint64_t sigB;
+ bool signZ;
+ uint64_t magBits;
+ struct exp16_sig64 normExpSig;
+ int16_t expZ;
+ struct uint128 sig128Z;
+ uint64_t sigZ, uiZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+ signB = signF64UI(b);
+ expB = expF64UI(b);
+ sigB = fracF64UI(b);
+ signZ = signA ^ signB;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FF) {
+ if (sigA || ((expB == 0x7FF) && sigB)) goto propagateNaN;
+ magBits = expB | sigB;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infArg;
+ }
+ if (expB == 0x7FF) {
+ if (sigB) goto propagateNaN;
+ magBits = expA | sigA;
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto infArg;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! sigB) {
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ goto zero;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA + expB - 0x3FF;
+ sigA = (sigA | UINT64_C(0x0010000000000000))<<10;
+ sigB = (sigB | UINT64_C(0x0010000000000000))<<11;
+ sig128Z = softfloat_mul64To128(sigA, sigB);
+ sigZ = sig128Z.v64 | (sig128Z.v0 != 0);
+ if (sigZ < UINT64_C(0x4000000000000000)) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ return softfloat_roundPackToF64(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF64UI(a, b, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infArg:
+ if (! magBits) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ = defaultNaNF64UI;
+ } else {
+ uiZ = packToF64UI(signZ, 0x7FF, 0);
+ }
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zero:
+ return packToF64UI(signZ, 0, 0);
+}
diff --git a/src/cpu/softfloat3e/f64_mulAdd.c b/src/cpu/softfloat3e/f64_mulAdd.c
new file mode 100644
index 0000000000..9623b49800
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_mulAdd.c
@@ -0,0 +1,243 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+#include "specialize.h"
+
+float64 f64_mulAdd(float64 a, float64 b, float64 c, uint8_t op, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ bool signB;
+ int16_t expB;
+ uint64_t sigB;
+ bool signC;
+ int16_t expC;
+ uint64_t sigC;
+ bool signZ;
+ uint64_t magBits, uiA, uiB, uiC, uiZ;
+ struct exp16_sig64 normExpSig;
+ int16_t expZ;
+ struct uint128 sig128Z;
+ uint64_t sigZ;
+ int16_t expDiff;
+ struct uint128 sig128C;
+ int8_t shiftDist;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiA = a;
+ uiB = b;
+ uiC = c;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF64UI(uiA);
+ expA = expF64UI(uiA);
+ sigA = fracF64UI(uiA);
+ signB = signF64UI(uiB);
+ expB = expF64UI(uiB);
+ sigB = fracF64UI(uiB);
+ signC = signF64UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0);
+ expC = expF64UI(uiC);
+ sigC = fracF64UI(uiC);
+ signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ bool aisNaN = (expA == 0x7FF) && sigA;
+ bool bisNaN = (expB == 0x7FF) && sigB;
+ bool cisNaN = (expC == 0x7FF) && sigC;
+ if (aisNaN | bisNaN | cisNaN) {
+ uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF64UI(uiA, uiB, status) : 0;
+ return softfloat_propagateNaNF64UI(uiZ, uiC, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ if (!expC) sigC = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FF) {
+ magBits = expB | sigB;
+ goto infProdArg;
+ }
+ if (expB == 0x7FF) {
+ magBits = expA | sigA;
+ goto infProdArg;
+ }
+ if (expC == 0x7FF) {
+ if ((sigA && !expA) || (sigB && !expB)) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ return packToF64UI(signC, 0x7FF, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigA);
+ expA = normExpSig.exp;
+ sigA = normExpSig.sig;
+ }
+ if (! expB) {
+ if (! sigB) goto zeroProd;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigB);
+ expB = normExpSig.exp;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expZ = expA + expB - 0x3FE;
+ sigA = (sigA | UINT64_C(0x0010000000000000))<<10;
+ sigB = (sigB | UINT64_C(0x0010000000000000))<<10;
+ sig128Z = softfloat_mul64To128(sigA, sigB);
+ if (sig128Z.v64 < UINT64_C(0x2000000000000000)) {
+ --expZ;
+ sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0);
+ }
+ if (! expC) {
+ if (! sigC) {
+ --expZ;
+ sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0);
+ goto roundPack;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigC);
+ expC = normExpSig.exp;
+ sigC = normExpSig.sig;
+ }
+ sigC = (sigC | UINT64_C(0x0010000000000000))<<9;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expZ - expC;
+ if (expDiff < 0) {
+ expZ = expC;
+ if ((signZ == signC) || (expDiff < -1)) {
+ sig128Z.v64 = softfloat_shiftRightJam64(sig128Z.v64, -expDiff);
+ } else {
+ sig128Z = softfloat_shortShiftRightJam128(sig128Z.v64, sig128Z.v0, 1);
+ }
+ } else if (expDiff) {
+ sig128C = softfloat_shiftRightJam128(sigC, 0, expDiff);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (signZ == signC) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff <= 0) {
+ sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0);
+ } else {
+ sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0);
+ sigZ = sig128Z.v64 | (sig128Z.v0 != 0);
+ }
+ if (sigZ < UINT64_C(0x4000000000000000)) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff < 0) {
+ signZ = signC;
+ sig128Z = softfloat_sub128(sigC, 0, sig128Z.v64, sig128Z.v0);
+ } else if (! expDiff) {
+ sig128Z.v64 = sig128Z.v64 - sigC;
+ if (! (sig128Z.v64 | sig128Z.v0)) goto completeCancellation;
+ if (sig128Z.v64 & UINT64_C(0x8000000000000000)) {
+ signZ = ! signZ;
+ sig128Z = softfloat_sub128(0, 0, sig128Z.v64, sig128Z.v0);
+ }
+ } else {
+ sig128Z = softfloat_sub128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0);
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (! sig128Z.v64) {
+ expZ -= 64;
+ sig128Z.v64 = sig128Z.v0;
+ sig128Z.v0 = 0;
+ }
+ shiftDist = softfloat_countLeadingZeros64(sig128Z.v64) - 1;
+ expZ -= shiftDist;
+ if (shiftDist < 0) {
+ sigZ = softfloat_shortShiftRightJam64(sig128Z.v64, -shiftDist);
+ } else {
+ sig128Z = softfloat_shortShiftLeft128(sig128Z.v64, sig128Z.v0, shiftDist);
+ sigZ = sig128Z.v64;
+ }
+ sigZ |= (sig128Z.v0 != 0);
+ }
+ roundPack:
+ return softfloat_roundPackToF64(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ infProdArg:
+ if (magBits) {
+ uiZ = packToF64UI(signZ, 0x7FF, 0);
+ if (signZ == signC || expC != 0x7FF) {
+ if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return uiZ;
+ }
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ uiZ = defaultNaNF64UI;
+ return softfloat_propagateNaNF64UI(uiZ, uiC, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ zeroProd:
+ uiZ = packToF64UI(signC, expC, sigC);
+ if (!expC && sigC) {
+ /* Exact zero plus a denormal */
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ if (softfloat_flushUnderflowToZero(status)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
+ return packToF64UI(signC, 0, 0);
+ }
+ }
+ if (! (expC | sigC) && (signZ != signC)) {
+ completeCancellation:
+ uiZ = packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0);
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f64_range.c b/src/cpu/softfloat3e/f64_range.c
new file mode 100644
index 0000000000..6f01c84cce
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_range.c
@@ -0,0 +1,135 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f64_range(float64 a, float64 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ bool signB;
+ int16_t expB;
+ uint64_t sigB;
+ bool aIsNaN, bIsNaN;
+ uint64_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+ signB = signF64UI(b);
+ expB = expF64UI(b);
+ sigB = fracF64UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_isSigNaNF64UI(a)) {
+ return softfloat_propagateNaNF64UI(a, 0, status);
+ }
+ if (softfloat_isSigNaNF64UI(b)) {
+ return softfloat_propagateNaNF64UI(b, 0, status);
+ }
+
+ aIsNaN = isNaNF64UI(a);
+ bIsNaN = isNaNF64UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA && sigA) {
+ if (softfloat_denormalsAreZeros(status)) {
+ a = packToF64UI(signA, 0, 0);
+ }
+ else if (! bIsNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ }
+
+ if (! expB && sigB) {
+ if (softfloat_denormalsAreZeros(status)) {
+ b = packToF64UI(signB, 0, 0);
+ }
+ else if (! aIsNaN) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (bIsNaN) {
+ z = a;
+ }
+ else if (aIsNaN) {
+ z = b;
+ }
+ else if (signA != signB && ! is_abs) {
+ if (! is_max) {
+ z = signA ? a : b;
+ } else {
+ z = signA ? b : a;
+ }
+ } else {
+ float64 tmp_a = a, tmp_b = b;
+ if (is_abs) {
+ tmp_a = tmp_a & ~UINT64_C(0x8000000000000000); // clear the sign bit
+ tmp_b = tmp_b & ~UINT64_C(0x8000000000000000);
+ signA = 0;
+ }
+
+ if (! is_max) {
+ z = (signA ^ (tmp_a < tmp_b)) ? a : b;
+ } else {
+ z = (signA ^ (tmp_a < tmp_b)) ? b : a;
+ }
+ }
+
+ switch(sign_ctrl) {
+ case 0:
+ z = (z & ~UINT64_C(0x8000000000000000)) | (a & UINT64_C(0x8000000000000000)); // keep sign of a
+ break;
+ case 1:
+ break; // preserve sign of compare result
+ case 2:
+ z = z & ~UINT64_C(0x8000000000000000); // zero out the sign bit
+ break;
+ case 3:
+ z = z | UINT64_C(0x8000000000000000); // set the sign bit
+ break;
+ }
+
+ return z;
+}
diff --git a/src/cpu/softfloat3e/f64_roundToInt.c b/src/cpu/softfloat3e/f64_roundToInt.c
new file mode 100644
index 0000000000..3c5f7fb8c2
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_roundToInt.c
@@ -0,0 +1,112 @@
+/*============================================================================
+
+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, 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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f64_roundToInt(float64 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ int64_t frac;
+ bool sign;
+ uint64_t uiZ, lastBitMask, roundBitsMask;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ scale &= 0xF;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF64UI(a);
+ frac = fracF64UI(a);
+ sign = signF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (0x433 <= (exp + scale)) {
+ if ((exp == 0x7FF) && frac) {
+ return softfloat_propagateNaNF64UI(a, 0, status);
+ }
+ return a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!exp) {
+ frac = 0;
+ a = packToF64UI(sign, 0, 0);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((exp + scale) <= 0x3FE) {
+ if (!(exp | frac)) return a;
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ uiZ = packToF64UI(sign, 0, 0);
+ switch (roundingMode) {
+ case softfloat_round_near_even:
+ if (!frac) break;
+ case softfloat_round_near_maxMag:
+ if ((exp + scale) == 0x3FE) uiZ |= packToF64UI(0, 0x3FF - scale, 0);
+ break;
+ case softfloat_round_min:
+ if (uiZ) uiZ = packToF64UI(1, 0x3FF - scale, 0);
+ break;
+ case softfloat_round_max:
+ if (!uiZ) uiZ = packToF64UI(0, 0x3FF - scale, 0);
+ break;
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ = a;
+ lastBitMask = (uint64_t) 1<<(0x433 - exp - scale);
+ roundBitsMask = lastBitMask - 1;
+ if (roundingMode == softfloat_round_near_maxMag) {
+ uiZ += lastBitMask>>1;
+ } else if (roundingMode == softfloat_round_near_even) {
+ uiZ += lastBitMask>>1;
+ if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask;
+ } else if (roundingMode == (signF64UI(uiZ) ? softfloat_round_min : softfloat_round_max)) {
+ uiZ += roundBitsMask;
+ }
+ uiZ &= ~roundBitsMask;
+ if (uiZ != a) {
+ if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f64_scalef.c b/src/cpu/softfloat3e/f64_scalef.c
new file mode 100644
index 0000000000..7a552ccc3b
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_scalef.c
@@ -0,0 +1,156 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+/*----------------------------------------------------------------------------
+| Return the result of a floating point scale of the double-precision floating
+| point value `a' by multiplying it by 2 power of the double-precision
+| floating point value 'b' converted to integral value. If the result cannot
+| be represented in double precision, then the proper overflow response (for
+| positive scaling operand), or the proper underflow response (for negative
+| scaling operand) is issued. The operation is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+float64 f64_scalef(float64 a, float64 b, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ bool signB;
+ int16_t expB;
+ uint64_t sigB;
+ int shiftCount;
+ int scale = 0;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+ signB = signF64UI(b);
+ expB = expF64UI(b);
+ sigB = fracF64UI(b);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expB == 0x7FF) {
+ if (sigB) return softfloat_propagateNaNF64UI(a, b, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) sigA = 0;
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FF) {
+ if (sigA) {
+ int aIsSignalingNaN = (sigA & UINT64_C(0x0008000000000000)) == 0;
+ if (aIsSignalingNaN || expB != 0x7FF || sigB)
+ return softfloat_propagateNaNF64UI(a, b, status);
+
+ return signB ? 0 : packToF64UI(0, 0x7FF, 0);
+ }
+
+ if (expB == 0x7FF && signB) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ }
+
+ return a;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ if (expB == 0x7FF && ! signB) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+ }
+ return packToF64UI(signA, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((expB | sigB) == 0) return a;
+
+ if (expB == 0x7FF) {
+ if (signB) return packToF64UI(signA, 0, 0);
+ return packToF64UI(signA, 0x7FF, 0);
+ }
+
+ if (0x40F <= expB) {
+ // handle obvious overflow/underflow result
+ return softfloat_roundPackToF64(signA, signB ? -0x3FF : 0x7FF, sigA, status);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expB < 0x3FF) {
+ if (expB == 0)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ scale = -signB;
+ }
+ else {
+ sigB |= UINT64_C(0x0010000000000000);
+ shiftCount = 0x433 - expB;
+ uint64_t prev_sigB = sigB;
+ sigB >>= shiftCount;
+ scale = (int32_t) sigB;
+ if (signB) {
+ if ((sigB< 0x1000) scale = 0x1000;
+ if (scale < -0x1000) scale = -0x1000;
+ }
+
+ if (expA != 0) {
+ sigA |= UINT64_C(0x0010000000000000);
+ } else {
+ expA++;
+ }
+
+ expA += scale - 1;
+ sigA <<= 10;
+ return softfloat_normRoundPackToF64(signA, expA, sigA, status);
+}
diff --git a/src/cpu/softfloat3e/f64_sqrt.c b/src/cpu/softfloat3e/f64_sqrt.c
new file mode 100644
index 0000000000..d3ea81af86
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_sqrt.c
@@ -0,0 +1,130 @@
+/*============================================================================
+
+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, 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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float64 f64_sqrt(float64 a, struct softfloat_status_t *status)
+{
+ bool signA;
+ int16_t expA;
+ uint64_t sigA;
+ struct exp16_sig64 normExpSig;
+ int16_t expZ;
+ uint32_t sig32A, recipSqrt32, sig32Z;
+ uint64_t rem;
+ uint32_t q;
+ uint64_t sigZ, shiftedSigZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ signA = signF64UI(a);
+ expA = expF64UI(a);
+ sigA = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FF) {
+ if (sigA) {
+ return softfloat_propagateNaNF64UI(a, 0, status);
+ }
+ if (! signA) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) {
+ sigA = 0;
+ a = packToF64UI(signA, 0, 0);
+ }
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (signA) {
+ if (! (expA | sigA)) return a;
+ goto invalid;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) return a;
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(sigA);
+ 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 - 0x3FF)>>1) + 0x3FE;
+ expA &= 1;
+ sigA |= UINT64_C(0x0010000000000000);
+ sig32A = sigA>>21;
+ recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A);
+ sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32;
+ if (expA) {
+ sigA <<= 8;
+ sig32Z >>= 1;
+ } else {
+ sigA <<= 9;
+ }
+ rem = sigA - (uint64_t) sig32Z * sig32Z;
+ q = ((uint32_t) (rem>>2) * (uint64_t) recipSqrt32)>>32;
+ sigZ = ((uint64_t) sig32Z<<32 | 1<<5) + ((uint64_t) q<<3);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if ((sigZ & 0x1FF) < 0x22) {
+ sigZ &= ~(uint64_t) 0x3F;
+ shiftedSigZ = sigZ>>6;
+ rem = (sigA<<52) - shiftedSigZ * shiftedSigZ;
+ if (rem & UINT64_C(0x8000000000000000)) {
+ --sigZ;
+ } else {
+ if (rem) sigZ |= 1;
+ }
+ }
+ return softfloat_roundPackToF64(0, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return defaultNaNF64UI;
+}
diff --git a/src/cpu/softfloat3e/f64_to_extF80.cc b/src/cpu/softfloat3e/f64_to_extF80.cc
new file mode 100644
index 0000000000..88b27f9d3c
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_extF80.cc
@@ -0,0 +1,88 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t f64_to_extF80(float64 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t frac;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ uint16_t uiZ64;
+ uint64_t uiZ0;
+ struct exp16_sig64 normExpSig;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ frac = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FF) {
+ if (frac) {
+ softfloat_f64UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToExtF80UI(&commonNaN);
+ uiZ64 = uiZ.v64;
+ uiZ0 = uiZ.v0;
+ } else {
+ uiZ64 = packToExtF80UI64(sign, 0x7FFF);
+ uiZ0 = UINT64_C(0x8000000000000000);
+ }
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac) {
+ return packToExtF80(sign, 0, 0);
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(frac);
+ exp = normExpSig.exp;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ uiZ64 = packToExtF80UI64(sign, exp + 0x3C00);
+ uiZ0 = (frac | UINT64_C(0x0010000000000000))<<11;
+ return packToExtF80_twoargs(uiZ64, uiZ0);
+}
diff --git a/src/cpu/softfloat3e/f64_to_f128.cc b/src/cpu/softfloat3e/f64_to_f128.cc
new file mode 100644
index 0000000000..cfae728249
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_f128.cc
@@ -0,0 +1,89 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float128_t f64_to_f128(float64 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t frac;
+ struct commonNaN commonNaN;
+ struct uint128 uiZ;
+ struct exp16_sig64 normExpSig;
+ struct uint128 frac128;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ frac = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FF) {
+ if (frac) {
+ softfloat_f64UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF128UI(&commonNaN);
+ } else {
+ uiZ.v64 = packToF128UI64(sign, 0x7FFF, 0);
+ uiZ.v0 = 0;
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! exp) {
+ if (! frac) {
+ uiZ.v64 = packToF128UI64(sign, 0, 0);
+ uiZ.v0 = 0;
+ return uiZ;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalF64Sig(frac);
+ exp = normExpSig.exp - 1;
+ frac = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac128 = softfloat_shortShiftLeft128(0, frac, 60);
+ uiZ.v64 = packToF128UI64(sign, exp + 0x3C00, frac128.v64);
+ uiZ.v0 = frac128.v0;
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/f64_to_f16.c b/src/cpu/softfloat3e/f64_to_f16.c
new file mode 100644
index 0000000000..fe8dea057a
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_f16.c
@@ -0,0 +1,83 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 f64_to_f16(float64 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t frac;
+ struct commonNaN commonNaN;
+ uint16_t uiZ, frac16;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ frac = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FF) {
+ if (frac) {
+ softfloat_f64UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF16UI(&commonNaN);
+ } else {
+ uiZ = packToF16UI(sign, 0x1F, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (!exp && frac) {
+ if (softfloat_denormalsAreZeros(status))
+ return packToF16UI(sign, 0, 0);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac16 = softfloat_shortShiftRightJam64(frac, 38);
+ if (! (exp | frac16)) {
+ return packToF16UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return softfloat_roundPackToF16(sign, exp - 0x3F1, frac16 | 0x4000, status);
+}
diff --git a/src/cpu/softfloat3e/f64_to_f32.c b/src/cpu/softfloat3e/f64_to_f32.c
new file mode 100644
index 0000000000..7ebbf428f3
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_f32.c
@@ -0,0 +1,83 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float32 f64_to_f32(float64 a, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t frac;
+ struct commonNaN commonNaN;
+ uint32_t uiZ, frac32;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ frac = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp == 0x7FF) {
+ if (frac) {
+ softfloat_f64UIToCommonNaN(a, &commonNaN, status);
+ uiZ = softfloat_commonNaNToF32UI(&commonNaN);
+ } else {
+ uiZ = packToF32UI(sign, 0xFF, 0);
+ }
+ return uiZ;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (!exp && frac) {
+ if (softfloat_denormalsAreZeros(status))
+ return packToF32UI(sign, 0, 0);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ frac32 = softfloat_shortShiftRightJam64(frac, 22);
+ if (! (exp | frac32)) {
+ return packToF32UI(sign, 0, 0);
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ return softfloat_roundPackToF32(sign, exp - 0x381, frac32 | 0x40000000, status);
+}
diff --git a/src/cpu/softfloat3e/f64_to_i32.c b/src/cpu/softfloat3e/f64_to_i32.c
new file mode 100644
index 0000000000..c296e0bd5e
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_i32.c
@@ -0,0 +1,77 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f64_to_i32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
+ if ((exp == 0x7FF) && sig) {
+#if (i32_fromNaN == i32_fromPosOverflow)
+ sign = 0;
+#elif (i32_fromNaN == i32_fromNegOverflow)
+ sign = 1;
+#else
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return i32_fromNaN;
+#endif
+ }
+#endif
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= UINT64_C(0x0010000000000000);
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ shiftDist = 0x427 - exp;
+ if (0 < shiftDist) sig = softfloat_shiftRightJam64(sig, shiftDist);
+ return softfloat_roundToI32(sign, sig, roundingMode, exact, status);
+}
+
diff --git a/src/cpu/softfloat3e/f64_to_i32_r_minMag.c b/src/cpu/softfloat3e/f64_to_i32_r_minMag.c
new file mode 100644
index 0000000000..80e2d6bc3e
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_i32_r_minMag.c
@@ -0,0 +1,89 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int32_t f64_to_i32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+ bool sign;
+ int32_t absZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x433 - exp;
+ if (53 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ if (shiftDist < 22) {
+ if (sign && (exp == 0x41E) && (sig < UINT64_C(0x0000000000200000))) {
+ if (exact && sig) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return -0x7FFFFFFF - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x7FF) && sig
+ ? i32_fromNaN
+ : sign ? i32_fromNegOverflow : i32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig |= UINT64_C(0x0010000000000000);
+ absZ = sig>>shiftDist;
+ if (exact && ((uint64_t) (uint32_t) absZ<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f64_to_i64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+ struct uint64_extra sigExtra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= UINT64_C(0x0010000000000000);
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ shiftDist = 0x433 - exp;
+ if (shiftDist <= 0) {
+ if (shiftDist < -11) goto invalid;
+ sigExtra.v = sig<<-shiftDist;
+ sigExtra.extra = 0;
+ } else {
+ sigExtra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist);
+ }
+ return softfloat_roundToI64(sign, sigExtra.v, sigExtra.extra, roundingMode, exact, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x7FF) && fracF64UI(a)
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+}
+
diff --git a/src/cpu/softfloat3e/f64_to_i64_r_minMag.c b/src/cpu/softfloat3e/f64_to_i64_r_minMag.c
new file mode 100644
index 0000000000..eb633eb227
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_i64_r_minMag.c
@@ -0,0 +1,95 @@
+
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+int64_t f64_to_i64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+ uint64_t absZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x433 - exp;
+ if (shiftDist <= 0) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (shiftDist < -10) {
+ if (a == packToF64UI(1, 0x43E, 0)) {
+ return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x7FF) && sig
+ ? i64_fromNaN
+ : sign ? i64_fromNegOverflow : i64_fromPosOverflow;
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sig |= UINT64_C(0x0010000000000000);
+ absZ = sig<<-shiftDist;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (53 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sig |= UINT64_C(0x0010000000000000);
+ absZ = sig>>shiftDist;
+ if (exact && (absZ<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f64_to_ui32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
+ if ((exp == 0x7FF) && sig) {
+#if (ui32_fromNaN == ui32_fromPosOverflow)
+ sign = 0;
+#elif (ui32_fromNaN == ui32_fromNegOverflow)
+ sign = 1;
+#else
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return ui32_fromNaN;
+#endif
+ }
+#endif
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= UINT64_C(0x0010000000000000);
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ shiftDist = 0x427 - exp;
+ if (0 < shiftDist) sig = softfloat_shiftRightJam64(sig, shiftDist);
+ return softfloat_roundToUI32(sign, sig, roundingMode, exact, status);
+}
diff --git a/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c b/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c
new file mode 100644
index 0000000000..7610d7c371
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c
@@ -0,0 +1,83 @@
+
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint32_t f64_to_ui32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+ bool sign;
+ uint32_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x433 - exp;
+ if (53 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ if (sign || (shiftDist < 21)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x7FF) && sig
+ ? ui32_fromNaN
+ : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sig |= UINT64_C(0x0010000000000000);
+ z = sig>>shiftDist;
+ if (exact && ((uint64_t) z<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f64_to_ui64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
+{
+ bool sign;
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+ struct uint64_extra sigExtra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (exp) sig |= UINT64_C(0x0010000000000000);
+ else if (softfloat_denormalsAreZeros(status)) sig = 0;
+ shiftDist = 0x433 - exp;
+ if (shiftDist <= 0) {
+ if (shiftDist < -11) goto invalid;
+ sigExtra.v = sig<<-shiftDist;
+ sigExtra.extra = 0;
+ } else {
+ sigExtra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist);
+ }
+ return softfloat_roundToUI64(sign, sigExtra.v, sigExtra.extra, roundingMode, exact, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return (exp == 0x7FF) && fracF64UI(a)
+ ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+}
diff --git a/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c
new file mode 100644
index 0000000000..e7bda4c67e
--- /dev/null
+++ b/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c
@@ -0,0 +1,87 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+uint64_t f64_to_ui64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status)
+{
+ int16_t exp;
+ uint64_t sig;
+ int16_t shiftDist;
+ bool sign;
+ uint64_t z;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ exp = expF64UI(a);
+ sig = fracF64UI(a);
+ if (softfloat_denormalsAreZeros(status))
+ if (!exp && sig) sig = 0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftDist = 0x433 - exp;
+ if (53 <= shiftDist) {
+ if (exact && (exp | sig)) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ return 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ sign = signF64UI(a);
+ if (sign) goto invalid;
+ if (shiftDist <= 0) {
+ if (shiftDist < -11) goto invalid;
+ z = (sig | UINT64_C(0x0010000000000000))<<-shiftDist;
+ } else {
+ sig |= UINT64_C(0x0010000000000000);
+ z = sig>>shiftDist;
+ if (exact && (uint64_t) (sig<<(-shiftDist & 63))) {
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ }
+ }
+ return z;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ invalid:
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
+ return
+ (exp == 0x7FF) && sig ? ui64_fromNaN
+ : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
+}
diff --git a/src/cpu/softfloat/fpatan.cc b/src/cpu/softfloat3e/fpatan.cc
similarity index 59%
rename from src/cpu/softfloat/fpatan.cc
rename to src/cpu/softfloat3e/fpatan.cc
index f33a3ff667..207dc320a7 100644
--- a/src/cpu/softfloat/fpatan.cc
+++ b/src/cpu/softfloat3e/fpatan.cc
@@ -25,27 +25,31 @@ these four paragraphs for those parts of this code that are retained.
#define FLOAT128
-#include "softfloatx80.h"
-#include "softfloat-round-pack.h"
+#include "config.h"
+#include "softfloat.h"
+#include "specialize.h"
+
+#include "fpu_trans.h"
#include "fpu_constant.h"
+#include "poly.h"
#define FPATAN_ARR_SIZE 11
-static const float128 float128_one =
+static const float128_t float128_one =
packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000));
-static const float128 float128_sqrt3 =
+static const float128_t float128_sqrt3 =
packFloat128(BX_CONST64(0x3fffbb67ae8584ca), BX_CONST64(0xa73b25742d7078b8));
static const floatx80 floatx80_pi =
packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
-static const float128 float128_pi2 =
+static const float128_t float128_pi2 =
packFloat128(BX_CONST64(0x3fff921fb54442d1), BX_CONST64(0x8469898CC5170416));
-static const float128 float128_pi4 =
+static const float128_t float128_pi4 =
packFloat128(BX_CONST64(0x3ffe921fb54442d1), BX_CONST64(0x8469898CC5170416));
-static const float128 float128_pi6 =
+static const float128_t float128_pi6 =
packFloat128(BX_CONST64(0x3ffe0c152382d736), BX_CONST64(0x58465BB32E0F580F));
-static float128 atan_arr[FPATAN_ARR_SIZE] =
+static float128_t atan_arr[FPATAN_ARR_SIZE] =
{
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */
@@ -60,10 +64,10 @@ static float128 atan_arr[FPATAN_ARR_SIZE] =
PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */
};
-extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status);
+extern float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status);
/* |x| < 1/4 */
-static float128 poly_atan(float128 x1, struct float_status_t *status)
+static float128_t poly_atan(float128_t x1, softfloat_status_t &status)
{
/*
// 3 5 7 9 11 13 15 17
@@ -86,12 +90,11 @@ static float128 poly_atan(float128 x1, struct float_status_t *status)
// atan(x) ~ x * [ p(x) + x * q(x) ]
//
*/
- return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE, status);
+ return OddPoly(x1, (const float128_t*) atan_arr, FPATAN_ARR_SIZE, status);
}
// =================================================
-// FPATAN Compute y * log (x)
-// 2
+// FPATAN Compute arctan(y/x)
// =================================================
//
@@ -134,125 +137,129 @@ static float128 poly_atan(float128 x1, struct float_status_t *status)
// 3 5 7 9 2n+1
//
-floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status)
+floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+ const floatx80 floatx80_default_nan =
+ packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) {
- float_raise(status, float_flag_invalid);
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
+ softfloat_raiseFlags(&status, softfloat_flag_invalid);
return floatx80_default_nan;
}
- Bit64u aSig = extractFloatx80Frac(a);
- Bit32s aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
- Bit64u bSig = extractFloatx80Frac(b);
- Bit32s bExp = extractFloatx80Exp(b);
- int bSign = extractFloatx80Sign(b);
+ uint64_t aSig = extF80_fraction(a);
+ int32_t aExp = extF80_exp(a);
+ int aSign = extF80_sign(a);
+ uint64_t bSig = extF80_fraction(b);
+ int32_t bExp = extF80_exp(b);
+ int bSign = extF80_sign(b);
int zSign = aSign ^ bSign;
if (bExp == 0x7FFF)
{
- if ((Bit64u) (bSig<<1))
- return propagateFloatx80NaN(a, b, status);
+ if (bSig<<1)
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1))
- return propagateFloatx80NaN(a, b, status);
-
- if (aSign) { /* return 3PI/4 */
- return roundAndPackFloatx80(80, bSign,
- FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status);
- }
- else { /* return PI/4 */
- return roundAndPackFloatx80(80, bSign,
- FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
- }
+ if (aSig<<1)
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
+
+ if (aSign) /* return 3PI/4 */
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status);
+ else /* return PI/4 */
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
}
- if (aSig && (aExp == 0))
- float_raise(status, float_flag_denormal);
+ if (aSig && ! aExp)
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
/* return PI/2 */
- return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
}
if (aExp == 0x7FFF)
{
- if ((Bit64u) (aSig<<1))
- return propagateFloatx80NaN(a, b, status);
+ if (aSig<<1)
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
- if (bSig && (bExp == 0))
- float_raise(status, float_flag_denormal);
+ if (bSig && ! bExp)
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
return_PI_or_ZERO:
- if (aSign) { /* return PI */
- return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
- } else { /* return 0 */
- return packFloatx80(bSign, 0, 0);
- }
+ if (aSign) /* return PI */
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
+ else /* return 0 */
+ return packToExtF80(bSign, 0, 0);
}
- if (bExp == 0)
+ if (! bExp)
{
- if (bSig == 0) {
- if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
+ if (! bSig) {
+ if (aSig && ! aExp) softfloat_raiseFlags(&status, softfloat_flag_denormal);
goto return_PI_or_ZERO;
}
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig);
+ bExp = normExpSig.exp + 1;
+ bSig = normExpSig.sig;
}
- if (aExp == 0)
+ if (! aExp)
{
- if (aSig == 0) /* return PI/2 */
- return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
+ if (! aSig) /* return PI/2 */
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig);
+ aExp = normExpSig.exp + 1;
+ aSig = normExpSig.sig;
}
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact);
/* |a| = |b| ==> return PI/4 */
- if (aSig == bSig && aExp == bExp)
- return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
+ if (aSig == bSig && aExp == bExp) {
+ if (aSign)
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status);
+ else
+ return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
+ }
/* ******************************** */
/* using float128 for approximation */
/* ******************************** */
- float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status);
- float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status);
- float128 x;
+ float128_t a128 = softfloat_normRoundPackToF128(0, aExp-0x10, aSig, 0, &status);
+ float128_t b128 = softfloat_normRoundPackToF128(0, bExp-0x10, bSig, 0, &status);
+ float128_t x;
int swap = 0, add_pi6 = 0, add_pi4 = 0;
if (aExp > bExp || (aExp == bExp && aSig > bSig))
{
- x = float128_div(b128, a128, status);
+ x = f128_div(b128, a128, &status);
}
else {
- x = float128_div(a128, b128, status);
+ x = f128_div(a128, b128, &status);
swap = 1;
}
- Bit32s xExp = extractFloat128Exp(x);
+ int32_t xExp = expF128UI64(x.v64);
if (xExp <= FLOATX80_EXP_BIAS-40)
goto approximation_completed;
- if (x.hi >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1
+ if (x.v64 >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1
{
/*
arctan(x) = arctan((x-1)/(x+1)) + pi/4
*/
- float128 t1 = float128_sub(x, float128_one, status);
- float128 t2 = float128_add(x, float128_one, status);
- x = float128_div(t1, t2, status);
+ float128_t t1 = f128_sub(x, float128_one, &status);
+ float128_t t2 = f128_add(x, float128_one, &status);
+ x = f128_div(t1, t2, &status);
add_pi4 = 1;
}
else
@@ -263,26 +270,26 @@ floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status)
/*
arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6
*/
- float128 t1 = float128_mul(x, float128_sqrt3, status);
- float128 t2 = float128_add(x, float128_sqrt3, status);
- x = float128_sub(t1, float128_one, status);
- x = float128_div(x, t2, status);
+ float128_t t1 = f128_mul(x, float128_sqrt3, &status);
+ float128_t t2 = f128_add(x, float128_sqrt3, &status);
+ x = f128_sub(t1, float128_one, &status);
+ x = f128_div(x, t2, &status);
add_pi6 = 1;
}
}
x = poly_atan(x, status);
- if (add_pi6) x = float128_add(x, float128_pi6, status);
- if (add_pi4) x = float128_add(x, float128_pi4, status);
+ if (add_pi6) x = f128_add(x, float128_pi6, &status);
+ if (add_pi4) x = f128_add(x, float128_pi4, &status);
approximation_completed:
- if (swap) x = float128_sub(float128_pi2, x, status);
- floatx80 result = float128_to_floatx80(x, status);
+ if (swap) x = f128_sub(float128_pi2, x, &status);
+ floatx80 result = f128_to_extF80(x, &status);
if (zSign) floatx80_chs(result);
- int rSign = extractFloatx80Sign(result);
+ int rSign = extF80_sign(result);
if (!bSign && rSign)
- return floatx80_add(result, floatx80_pi, status);
+ return extF80_add(result, floatx80_pi, &status);
if (bSign && !rSign)
- return floatx80_sub(result, floatx80_pi, status);
+ return extF80_sub(result, floatx80_pi, &status);
return result;
}
diff --git a/src/cpu/softfloat/fprem.cc b/src/cpu/softfloat3e/fprem.cc
similarity index 53%
rename from src/cpu/softfloat/fprem.cc
rename to src/cpu/softfloat3e/fprem.cc
index 26637c5c57..2252f12307 100644
--- a/src/cpu/softfloat/fprem.cc
+++ b/src/cpu/softfloat3e/fprem.cc
@@ -23,100 +23,109 @@ these four paragraphs for those parts of this code that are retained.
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
-#include "softfloatx80.h"
-#include "softfloat-round-pack.h"
+#include "fpu_trans.h"
#define USE_estimateDiv128To64
-#include "softfloat-macros.h"
+#include "softfloat-helpers.h"
+
+#include "specialize.h" // for softfloat_propagateNaNExtF80UI
/* executes single exponent reduction cycle */
-static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1)
+static uint64_t remainder_kernel(uint64_t aSig0, uint64_t bSig, int expDiff, uint64_t *zSig0, uint64_t *zSig1)
{
- Bit64u term0, term1;
- Bit64u aSig1 = 0;
-
+ uint128 term, z;
+ uint64_t aSig1 = 0;
shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0);
- Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig);
- mul64To128(bSig, q, &term0, &term1);
- sub128(aSig1, aSig0, term0, term1, zSig1, zSig0);
- while ((Bit64s)(*zSig1) < 0) {
+ uint64_t q = estimateDiv128To64(aSig1, aSig0, bSig);
+ term = softfloat_mul64To128(bSig, q);
+ z = softfloat_sub128(aSig1, aSig0, term.v64, term.v0);
+ while ((int64_t) z.v64 < 0) {
--q;
- add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0);
+ z = softfloat_add128(z.v64, z.v0, 0, bSig);
}
+ *zSig0 = z.v0;
+ *zSig1 = z.v64;
return q;
}
-static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding_mode, struct float_status_t *status)
+static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, int rounding_mode, struct softfloat_status_t *status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+ static const floatx80 floatx80_default_nan =
+ packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
- Bit32s aExp, bExp, zExp, expDiff;
- Bit64u aSig0, aSig1, bSig;
+ int32_t aExp, bExp, zExp, expDiff;
+ uint64_t aSig0, aSig1 = 0, bSig;
int aSign;
+ struct exp32_sig64 normExpSig;
+ uint128 term;
+
*q = 0;
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
- {
- float_raise(status, float_flag_invalid);
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
*r = floatx80_default_nan;
return -1;
}
- aSig0 = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
+ aSig0 = extF80_fraction(a);
+ aExp = extF80_exp(a);
+ aSign = extF80_sign(a);
+ bSig = extF80_fraction(b);
+ bExp = extF80_exp(b);
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) {
- *r = propagateFloatx80NaN(a, b, status);
+ if ((aSig0<<1) || ((bExp == 0x7FFF) && (bSig<<1))) {
+ *r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status);
return -1;
}
- float_raise(status, float_flag_invalid);
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
*r = floatx80_default_nan;
return -1;
}
if (bExp == 0x7FFF) {
- if ((Bit64u) (bSig<<1)) {
- *r = propagateFloatx80NaN(a, b, status);
+ if (bSig << 1) {
+ *r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status);
return -1;
}
- if (aExp == 0 && aSig0) {
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
- *r = (a.fraction & BX_CONST64(0x8000000000000000)) ?
- packFloatx80(aSign, aExp, aSig0) : a;
+ if (! aExp && aSig0) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(aSig0);
+ aExp = normExpSig.exp + 1;
+ aSig0 = normExpSig.sig;
+ *r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a;
return 0;
}
*r = a;
return 0;
}
- if (bExp == 0) {
- if (bSig == 0) {
- float_raise(status, float_flag_invalid);
+ if (! bExp) {
+ if (! bSig) {
+ softfloat_raiseFlags(status, softfloat_flag_invalid);
*r = floatx80_default_nan;
return -1;
}
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(bSig);
+ bExp = normExpSig.exp + 1;
+ bSig = normExpSig.sig;
}
- if (aExp == 0) {
- if (aSig0 == 0) {
+ if (! aExp) {
+ if (! aSig0) {
*r = a;
return 0;
}
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(aSig0);
+ aExp = normExpSig.exp + 1;
+ aSig0 = normExpSig.sig;
}
- expDiff = aExp - bExp;
- aSig1 = 0;
- Bit32u overflow = 0;
+ expDiff = aExp - bExp;
+ int overflow = 0;
if (expDiff >= 64) {
int n = (expDiff & 0x1f) | 0x20;
@@ -129,11 +138,10 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding
if (expDiff < 0) {
if (expDiff < -1) {
- *r = (a.fraction & BX_CONST64(0x8000000000000000)) ?
- packFloatx80(aSign, aExp, aSig0) : a;
+ *r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a;
return 0;
}
- shift128Right(aSig0, 0, 1, &aSig0, &aSig1);
+ shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1);
expDiff = 0;
}
@@ -147,26 +155,28 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding
}
}
- if (rounding_mode == float_round_nearest_even)
- {
- Bit64u term0, term1;
- shift128Right(bSig, 0, 1, &term0, &term1);
-
- if (! lt128(aSig0, aSig1, term0, term1))
- {
- int lt = lt128(term0, term1, aSig0, aSig1);
- int eq = eq128(aSig0, aSig1, term0, term1);
-
- if ((eq && ((*q) & 1)) || lt) {
- aSign = !aSign;
- ++(*q);
- }
- if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1);
+ if (rounding_mode == softfloat_round_near_even) {
+ uint64_t term0, term1;
+ shortShift128Right(bSig, 0, 1, &term0, &term1);
+
+ if (! softfloat_lt128(aSig0, aSig1, term0, term1)) {
+ int lt = softfloat_lt128(term0, term1, aSig0, aSig1);
+ int eq = softfloat_eq128(aSig0, aSig1, term0, term1);
+
+ if ((eq && ((*q) & 1)) || lt) {
+ aSign = !aSign;
+ ++(*q);
+ }
+ if (lt) {
+ term = softfloat_sub128(bSig, 0, aSig0, aSig1);
+ aSig0 = term.v64;
+ aSig1 = term.v0;
+ }
}
}
}
- *r = normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status);
+ *r = softfloat_normRoundPackToExtF80(aSign, zExp, aSig0, aSig1, 80, status);
return overflow;
}
@@ -176,9 +186,9 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
-int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status)
+int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status)
{
- return do_fprem(a, b, r, q, float_round_nearest_even, status);
+ return do_fprem(a, b, r, q, softfloat_round_near_even, status);
}
/*----------------------------------------------------------------------------
@@ -190,7 +200,7 @@ int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, s
| quotient of 'a' divided by 'b' to an integer.
*----------------------------------------------------------------------------*/
-int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status)
+int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status)
{
- return do_fprem(a, b, r, q, float_round_to_zero, status);
+ return do_fprem(a, b, r, q, softfloat_round_to_zero, status);
}
diff --git a/src/cpu/softfloat/fpu_constant.h b/src/cpu/softfloat3e/fpu_constant.h
similarity index 98%
rename from src/cpu/softfloat/fpu_constant.h
rename to src/cpu/softfloat3e/fpu_constant.h
index 7a7fc6f1aa..d7d44ee3c1 100644
--- a/src/cpu/softfloat/fpu_constant.h
+++ b/src/cpu/softfloat3e/fpu_constant.h
@@ -24,7 +24,7 @@ these four paragraphs for those parts of this code that are retained.
#include "config.h"
// Pentium CPU uses only 68-bit precision M_PI approximation
-//#define BETTER_THAN_PENTIUM
+// #define BETTER_THAN_PENTIUM
/*============================================================================
* Written for Bochs (x86 achitecture simulator) by
diff --git a/src/cpu/softfloat3e/fpu_trans.h b/src/cpu/softfloat3e/fpu_trans.h
new file mode 100644
index 0000000000..bd3d3cecba
--- /dev/null
+++ b/src/cpu/softfloat3e/fpu_trans.h
@@ -0,0 +1,117 @@
+/////////////////////////////////////////////////////////////////////////
+// $Id$
+/////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003-2018 Stanislav Shwartsman
+// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+/////////////////////////////////////////////////////////////////////////
+
+#ifndef _FPU_TRANS_H_
+#define _FPU_TRANS_H_
+
+#include "softfloat.h"
+#include "softfloat-specialize.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision operations.
+*----------------------------------------------------------------------------*/
+
+int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status);
+int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status);
+
+floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status);
+#ifdef __cplusplus
+floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status);
+floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status);
+floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status);
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision trigonometric functions.
+*----------------------------------------------------------------------------*/
+
+int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status);
+int fsin(floatx80 &a, softfloat_status_t &status);
+int fcos(floatx80 &a, softfloat_status_t &status);
+int ftan(floatx80 &a, softfloat_status_t &status);
+#else
+floatx80 fyl2x(floatx80 a, floatx80 b, struct softfloat_status_t *status);
+floatx80 fyl2xp1(floatx80 a, floatx80 b, struct softfloat_status_t *status);
+floatx80 fpatan(floatx80 a, floatx80 b, struct softfloat_status_t *status);
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision trigonometric functions.
+*----------------------------------------------------------------------------*/
+
+int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct softfloat_status_t *status);
+int fsin(floatx80 *a, struct softfloat_status_t *status);
+int fcos(floatx80 *a, struct softfloat_status_t *status);
+int ftan(floatx80 *a, struct softfloat_status_t *status);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-----------------------------------------------------------------------------
+| Calculates the absolute value of the extended double-precision floating-point
+| value `a'. The operation is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+static __inline floatx80 &floatx80_abs(floatx80 ®)
+#else
+static __inline floatx80 floatx80_abs(floatx80 reg)
+#endif
+{
+ reg.signExp &= 0x7FFF;
+ return reg;
+}
+
+/*-----------------------------------------------------------------------------
+| Changes the sign of the extended double-precision floating-point value 'a'.
+| The operation is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+static __inline floatx80 &floatx80_chs(floatx80 ®)
+#else
+static __inline floatx80 floatx80_chs(floatx80 reg)
+#endif
+{
+ reg.signExp ^= 0x8000;
+ return reg;
+}
+
+#ifdef __cplusplus
+static __inline floatx80 FPU_round_const(const floatx80 &a, int adj)
+#else
+static __inline floatx80 FPU_round_const(const floatx80 a, int adj)
+#endif
+{
+ floatx80 result = a;
+ result.signif += adj;
+ return result;
+}
+
+#endif
diff --git a/src/cpu/softfloat/fsincos.cc b/src/cpu/softfloat3e/fsincos.cc
similarity index 68%
rename from src/cpu/softfloat/fsincos.cc
rename to src/cpu/softfloat3e/fsincos.cc
index f5b33a8230..1a2a018de8 100644
--- a/src/cpu/softfloat/fsincos.cc
+++ b/src/cpu/softfloat3e/fsincos.cc
@@ -26,24 +26,29 @@ these four paragraphs for those parts of this code that are retained.
#define FLOAT128
#define USE_estimateDiv128To64
-#include "softfloatx80.h"
-#include "softfloat-round-pack.h"
+#include "config.h"
+#include "specialize.h"
+
+#include "fpu_trans.h"
+#include "softfloat-helpers.h"
#include "fpu_constant.h"
+#include "poly.h"
+
static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
/* reduce trigonometric function argument using 128-bit precision
M_PI approximation */
-static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1)
+static uint64_t argument_reduction_kernel(uint64_t aSig0, int Exp, uint64_t *zSig0, uint64_t *zSig1)
{
- Bit64u term0, term1, term2;
- Bit64u aSig1 = 0;
+ uint64_t term0, term1, term2;
+ uint64_t aSig1 = 0;
shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0);
- Bit64u q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI);
+ uint64_t q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI);
mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2);
sub128(aSig1, aSig0, term0, term1, zSig1, zSig0);
- while ((Bit64s)(*zSig1) < 0) {
+ while ((int64_t)(*zSig1) < 0) {
--q;
add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2);
}
@@ -51,35 +56,35 @@ static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bi
return q;
}
-static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1)
+static int reduce_trig_arg(int expDiff, int &zSign, uint64_t &aSig0, uint64_t &aSig1)
{
- Bit64u term0, term1, q = 0;
+ uint64_t term0, term1, q = 0;
if (expDiff < 0) {
- shift128Right(*aSig0, 0, 1, aSig0, aSig1);
+ shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1);
expDiff = 0;
}
if (expDiff > 0) {
- q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1);
+ q = argument_reduction_kernel(aSig0, expDiff, &aSig0, &aSig1);
}
else {
- if (FLOAT_PI_HI <= *aSig0) {
- *aSig0 -= FLOAT_PI_HI;
+ if (FLOAT_PI_HI <= aSig0) {
+ aSig0 -= FLOAT_PI_HI;
q = 1;
}
}
- shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1);
- if (! lt128(*aSig0, *aSig1, term0, term1))
+ shortShift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1);
+ if (! softfloat_lt128(aSig0, aSig1, term0, term1))
{
- int lt = lt128(term0, term1, *aSig0, *aSig1);
- int eq = eq128(*aSig0, *aSig1, term0, term1);
+ int lt = softfloat_lt128(term0, term1, aSig0, aSig1);
+ int eq = softfloat_eq128(aSig0, aSig1, term0, term1);
if ((eq && (q & 1)) || lt) {
- *zSign = !(*zSign);
+ zSign = !zSign;
++q;
}
- if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1);
+ if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, aSig0, aSig1, &aSig0, &aSig1);
}
return (int)(q & 3);
@@ -88,7 +93,7 @@ static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1
#define SIN_ARR_SIZE 11
#define COS_ARR_SIZE 11
-static float128 sin_arr[SIN_ARR_SIZE] =
+static float128_t sin_arr[SIN_ARR_SIZE] =
{
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */
@@ -103,7 +108,7 @@ static float128 sin_arr[SIN_ARR_SIZE] =
PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */
};
-static float128 cos_arr[COS_ARR_SIZE] =
+static float128_t cos_arr[COS_ARR_SIZE] =
{
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */
PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */
@@ -118,10 +123,8 @@ static float128 cos_arr[COS_ARR_SIZE] =
PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */
};
-extern float128 OddPoly (float128 x, float128 *arr, int n, struct float_status_t *status);
-
/* 0 <= x <= pi/4 */
-BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status)
+static __inline float128_t poly_sin(float128_t x, softfloat_status_t &status)
{
// 3 5 7 9 11 13 15
// x x x x x x x
@@ -143,13 +146,11 @@ BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status)
// sin(x) ~ x * [ p(x) + x * q(x) ]
//
- return OddPoly(x, sin_arr, SIN_ARR_SIZE, status);
+ return OddPoly(x, (const float128_t*) sin_arr, SIN_ARR_SIZE, status);
}
-extern float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status);
-
/* 0 <= x <= pi/4 */
-BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status)
+static __inline float128_t poly_cos(float128_t x, softfloat_status_t &status)
{
// 2 4 6 8 10 12 14
// x x x x x x x
@@ -166,22 +167,22 @@ BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status)
// cos(x) ~ [ p(x) + x * q(x) ]
//
- return EvenPoly(x, cos_arr, COS_ARR_SIZE, status);
+ return EvenPoly(x, (const float128_t*) cos_arr, COS_ARR_SIZE, status);
}
-BX_CPP_INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
+static __inline void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
{
if (sin_a) *sin_a = a;
if (cos_a) *cos_a = a;
}
-BX_CPP_INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
+static __inline void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
{
if (sin_a) *sin_a = a;
if (cos_a) *cos_a = floatx80_one;
}
-static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struct float_status_t *status)
+static floatx80 sincos_approximation(int neg, float128_t r, uint64_t quotient, softfloat_status_t &status)
{
if (quotient & 0x1) {
r = poly_cos(r, status);
@@ -190,7 +191,7 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struc
r = poly_sin(r, status);
}
- floatx80 result = float128_to_floatx80(r, status);
+ floatx80 result = f128_to_extF80(r, &status);
if (quotient & 0x2)
neg = ! neg;
@@ -220,59 +221,62 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struc
// sin(x+2pi) = sin(x)
//
-int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status)
+int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+ const floatx80 floatx80_default_nan =
+ packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
- Bit64u aSig0, aSig1 = 0;
- Bit32s aExp, zExp, expDiff;
+ uint64_t aSig0, aSig1 = 0;
+ int32_t aExp, zExp, expDiff;
int aSign, zSign;
int q = 0;
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a)) {
+ if (extF80_isUnsupported(a)) {
goto invalid;
}
- aSig0 = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
+ aSig0 = extF80_fraction(a);
+ aExp = extF80_exp(a);
+ aSign = extF80_sign(a);
/* invalid argument */
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig0<<1)) {
- sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOne(a, status));
+ if (aSig0 << 1) {
+ sincos_invalid(sin_a, cos_a, softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status));
return 0;
}
invalid:
- float_raise(status, float_flag_invalid);
+ softfloat_raiseFlags(&status, softfloat_flag_invalid);
sincos_invalid(sin_a, cos_a, floatx80_default_nan);
return 0;
}
- if (aExp == 0) {
- if (aSig0 == 0) {
+ if (! aExp) {
+ if (! aSig0) {
sincos_tiny_argument(sin_a, cos_a, a);
return 0;
}
- float_raise(status, float_flag_denormal);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
/* handle pseudo denormals */
if (! (aSig0 & BX_CONST64(0x8000000000000000)))
{
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact);
if (sin_a)
- float_raise(status, float_flag_underflow);
+ softfloat_raiseFlags(&status, softfloat_flag_underflow);
sincos_tiny_argument(sin_a, cos_a, a);
return 0;
}
- normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0);
+ aExp = normExpSig.exp + 1;
+ aSig0 = normExpSig.sig;
}
zSign = aSign;
@@ -283,7 +287,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t
if (expDiff >= 63)
return -1;
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact);
if (expDiff < -1) { // doesn't require reduction
if (expDiff <= -68) {
@@ -294,7 +298,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t
zExp = aExp;
}
else {
- q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1);
+ q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1);
}
/* **************************** */
@@ -302,7 +306,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t
/* **************************** */
/* using float128 for approximation */
- float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status);
+ float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status);
if (aSign) q = -q;
if (sin_a) *sin_a = sincos_approximation(zSign, r, q, status);
@@ -311,14 +315,14 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t
return 0;
}
-int fsin(floatx80 *a, struct float_status_t *status)
+int fsin(floatx80 &a, softfloat_status_t &status)
{
- return fsincos(*a, a, 0, status);
+ return fsincos(a, &a, 0, status);
}
-int fcos(floatx80 *a, struct float_status_t *status)
+int fcos(floatx80 &a, softfloat_status_t &status)
{
- return fsincos(*a, 0, a, status);
+ return fsincos(a, 0, &a, status);
}
// =================================================
@@ -348,51 +352,55 @@ int fcos(floatx80 *a, struct float_status_t *status)
// cos(x)
//
-int ftan(floatx80 *a, struct float_status_t *status)
+int ftan(floatx80 &a, softfloat_status_t &status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
- const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+ const floatx80 floatx80_default_nan =
+ packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
- Bit64u aSig0, aSig1 = 0;
- Bit32s aExp, zExp, expDiff;
+ uint64_t aSig0, aSig1 = 0;
+ int32_t aExp, zExp, expDiff;
int aSign, zSign;
int q = 0;
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(*a)) {
+ if (extF80_isUnsupported(a)) {
goto invalid;
}
- aSig0 = extractFloatx80Frac(*a);
- aExp = extractFloatx80Exp(*a);
- aSign = extractFloatx80Sign(*a);
+ aSig0 = extF80_fraction(a);
+ aExp = extF80_exp(a);
+ aSign = extF80_sign(a);
/* invalid argument */
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig0<<1))
+ if (aSig0 << 1)
{
- *a = propagateFloatx80NaNOne(*a, status);
+ a = softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status);
return 0;
}
invalid:
- float_raise(status, float_flag_invalid);
- *a = floatx80_default_nan;
+ softfloat_raiseFlags(&status, softfloat_flag_invalid);
+ a = floatx80_default_nan;
return 0;
}
- if (aExp == 0) {
- if (aSig0 == 0) return 0;
- float_raise(status, float_flag_denormal);
+ if (! aExp) {
+ if (! aSig0) return 0;
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
/* handle pseudo denormals */
if (! (aSig0 & BX_CONST64(0x8000000000000000)))
{
- float_raise(status, float_flag_inexact | float_flag_underflow);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact | softfloat_flag_underflow);
return 0;
}
- normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0);
+ aExp = normExpSig.exp + 1;
+ aSig0 = normExpSig.sig;
}
zSign = aSign;
@@ -403,17 +411,17 @@ int ftan(floatx80 *a, struct float_status_t *status)
if (expDiff >= 63)
return -1;
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact);
if (expDiff < -1) { // doesn't require reduction
if (expDiff <= -68) {
- *a = packFloatx80(aSign, aExp, aSig0);
+ a = packFloatx80(aSign, aExp, aSig0);
return 0;
}
zExp = aExp;
}
else {
- q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1);
+ q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1);
}
/* **************************** */
@@ -421,21 +429,21 @@ int ftan(floatx80 *a, struct float_status_t *status)
/* **************************** */
/* using float128 for approximation */
- float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status);
+ float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status);
- float128 sin_r = poly_sin(r, status);
- float128 cos_r = poly_cos(r, status);
+ float128_t sin_r = poly_sin(r, status);
+ float128_t cos_r = poly_cos(r, status);
if (q & 0x1) {
- r = float128_div(cos_r, sin_r, status);
+ r = f128_div(cos_r, sin_r, &status);
zSign = ! zSign;
} else {
- r = float128_div(sin_r, cos_r, status);
+ r = f128_div(sin_r, cos_r, &status);
}
- *a = float128_to_floatx80(r, status);
+ a = f128_to_extF80(r, &status);
if (zSign)
- floatx80_chs(*a);
+ floatx80_chs(a);
return 0;
}
diff --git a/src/cpu/softfloat/fyl2x.cc b/src/cpu/softfloat3e/fyl2x.cc
similarity index 61%
rename from src/cpu/softfloat/fyl2x.cc
rename to src/cpu/softfloat3e/fyl2x.cc
index 875f866a91..7c90e6207f 100644
--- a/src/cpu/softfloat/fyl2x.cc
+++ b/src/cpu/softfloat3e/fyl2x.cc
@@ -24,29 +24,28 @@ these four paragraphs for those parts of this code that are retained.
* ==========================================================================*/
#define FLOAT128
-
-#include "softfloatx80.h"
-#include "softfloat-round-pack.h"
+#include "config.h"
+#include "fpu_trans.h"
+#include "specialize.h"
+#include "softfloat-helpers.h"
#include "fpu_constant.h"
+#include "poly.h"
-static const floatx80 floatx80_one =
- packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
+static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
-static const float128 float128_one =
+static const float128_t float128_one =
packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000));
-static const float128 float128_two =
+static const float128_t float128_two =
packFloat128(BX_CONST64(0x4000000000000000), BX_CONST64(0x0000000000000000));
-static const float128 float128_ln2inv2 =
+static const float128_t float128_ln2inv2 =
packFloat128(BX_CONST64(0x400071547652b82f), BX_CONST64(0xe1777d0ffda0d23a));
#define SQRT2_HALF_SIG BX_CONST64(0xb504f333f9de6484)
-extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status);
-
#define L2_ARR_SIZE 9
-static float128 ln_arr[L2_ARR_SIZE] =
+static float128_t ln_arr[L2_ARR_SIZE] =
{
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */
@@ -59,7 +58,7 @@ static float128 ln_arr[L2_ARR_SIZE] =
PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */
};
-static float128 poly_ln(float128 x1, struct float_status_t *status)
+static float128_t poly_ln(float128_t x1, softfloat_status_t &status)
{
/*
//
@@ -84,28 +83,28 @@ static float128 poly_ln(float128 x1, struct float_status_t *status)
// 1-u
//
*/
- return OddPoly(x1, ln_arr, L2_ARR_SIZE, status);
+ return OddPoly(x1, (const float128_t*) ln_arr, L2_ARR_SIZE, status);
}
/* required sqrt(2)/2 < x < sqrt(2) */
-static float128 poly_l2(float128 x, struct float_status_t *status)
+static float128_t poly_l2(float128_t x, softfloat_status_t &status)
{
/* using float128 for approximation */
- float128 x_p1 = float128_add(x, float128_one, status);
- float128 x_m1 = float128_sub(x, float128_one, status);
- x = float128_div(x_m1, x_p1, status);
+ float128_t x_p1 = f128_add(x, float128_one, &status);
+ float128_t x_m1 = f128_sub(x, float128_one, &status);
+ x = f128_div(x_m1, x_p1, &status);
x = poly_ln(x, status);
- x = float128_mul(x, float128_ln2inv2, status);
+ x = f128_mul(x, float128_ln2inv2, &status);
return x;
}
-static float128 poly_l2p1(float128 x, struct float_status_t *status)
+static float128_t poly_l2p1(float128_t x, softfloat_status_t &status)
{
/* using float128 for approximation */
- float128 x_p2 = float128_add(x, float128_two, status);
- x = float128_div(x, x_p2, status);
+ float128_t x_plus2 = f128_add(x, float128_two, &status);
+ x = f128_div(x, x_plus2, &status);
x = poly_ln(x, status);
- x = float128_mul(x, float128_ln2inv2, status);
+ x = f128_mul(x, float128_ln2inv2, &status);
return x;
}
@@ -134,7 +133,7 @@ static float128 poly_l2p1(float128 x, struct float_status_t *status)
// 1-u 3 5 7 2n+1
//
-floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status)
+floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
@@ -142,71 +141,73 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status)
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) {
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
invalid:
- float_raise(status, float_flag_invalid);
+ softfloat_raiseFlags(&status, softfloat_flag_invalid);
return floatx80_default_nan;
}
- Bit64u aSig = extractFloatx80Frac(a);
- Bit32s aExp = extractFloatx80Exp(a);
- int aSign = extractFloatx80Sign(a);
- Bit64u bSig = extractFloatx80Frac(b);
- Bit32s bExp = extractFloatx80Exp(b);
- int bSign = extractFloatx80Sign(b);
+ uint64_t aSig = extF80_fraction(a);
+ int32_t aExp = extF80_exp(a);
+ int aSign = extF80_sign(a);
+ uint64_t bSig = extF80_fraction(b);
+ int32_t bExp = extF80_exp(b);
+ int bSign = extF80_sign(b);
int zSign = bSign ^ 1;
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1)
- || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
- {
- return propagateFloatx80NaN(a, b, status);
+ if ((aSig<<1) || ((bExp == 0x7FFF) && (bSig<<1))) {
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
}
if (aSign) goto invalid;
else {
- if (bExp == 0) {
- if (bSig == 0) goto invalid;
- float_raise(status, float_flag_denormal);
+ if (! bExp) {
+ if (! bSig) goto invalid;
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
}
return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
}
- if (bExp == 0x7FFF)
- {
- if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
- if (aSign && (Bit64u)(aExp | aSig)) goto invalid;
- if (aSig && (aExp == 0))
- float_raise(status, float_flag_denormal);
+ if (bExp == 0x7FFF) {
+ if (bSig << 1)
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
+ if (aSign && (uint64_t)(aExp | aSig)) goto invalid;
+ if (aSig && ! aExp)
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
if (aExp < 0x3FFF) {
return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
- if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid;
+ if (aExp == 0x3FFF && ! (aSig<<1)) goto invalid;
return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
- if (aExp == 0) {
- if (aSig == 0) {
+ if (! aExp) {
+ if (! aSig) {
if ((bExp | bSig) == 0) goto invalid;
- float_raise(status, float_flag_divbyzero);
+ softfloat_raiseFlags(&status, softfloat_flag_divbyzero);
return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
if (aSign) goto invalid;
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig);
+ aExp = normExpSig.exp + 1;
+ aSig = normExpSig.sig;
}
if (aSign) goto invalid;
- if (bExp == 0) {
- if (bSig == 0) {
+ if (! bExp) {
+ if (! bSig) {
if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
return packFloatx80(bSign, 0, 0);
}
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig);
+ bExp = normExpSig.exp + 1;
+ bSig = normExpSig.sig;
}
- if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0))
+ if (aExp == 0x3FFF && ! (aSig<<1))
return packFloatx80(bSign, 0, 0);
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact);
int ExpDiff = aExp - 0x3FFF;
aExp = 0;
@@ -219,12 +220,15 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status)
/* using float128 for approximation */
/* ******************************** */
- Bit64u zSig0, zSig1;
- shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
- float128 x = packFloat128Four(0, aExp+0x3FFF, zSig0, zSig1);
+ float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status);
+
+ uint64_t zSig0, zSig1;
+ shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
+ float128_t x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
x = poly_l2(x, status);
- x = float128_add(x, int64_to_float128((Bit64s) ExpDiff), status);
- return floatx80_128_mul(b, x, status);
+ x = f128_add(x, i32_to_f128(ExpDiff), &status);
+ x = f128_mul(x, b128, &status);
+ return f128_to_extF80(x, &status);
}
// =================================================
@@ -252,112 +256,117 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status)
// 1-u 3 5 7 2n+1
//
-floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status)
+floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status)
{
+ int32_t aExp, bExp;
+ uint64_t aSig, bSig, zSig0, zSig1, zSig2;
+ int aSign, bSign;
+
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
- Bit32s aExp, bExp;
- Bit64u aSig, bSig, zSig0, zSig1, zSig2;
- int aSign, bSign;
-
// handle unsupported extended double-precision floating encodings
- if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) {
+ if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
invalid:
- float_raise(status, float_flag_invalid);
+ softfloat_raiseFlags(&status, softfloat_flag_invalid);
return floatx80_default_nan;
}
- aSig = extractFloatx80Frac(a);
- aExp = extractFloatx80Exp(a);
- aSign = extractFloatx80Sign(a);
- bSig = extractFloatx80Frac(b);
- bExp = extractFloatx80Exp(b);
- bSign = extractFloatx80Sign(b);
+
+ aSig = extF80_fraction(a);
+ aExp = extF80_exp(a);
+ aSign = extF80_sign(a);
+ bSig = extF80_fraction(b);
+ bExp = extF80_exp(b);
+ bSign = extF80_sign(b);
int zSign = aSign ^ bSign;
if (aExp == 0x7FFF) {
- if ((Bit64u) (aSig<<1)
- || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
- {
- return propagateFloatx80NaN(a, b, status);
+ if ((aSig<<1) != 0 || ((bExp == 0x7FFF) && (bSig<<1) != 0)) {
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
}
if (aSign) goto invalid;
else {
- if (bExp == 0) {
- if (bSig == 0) goto invalid;
- float_raise(status, float_flag_denormal);
+ if (! bExp) {
+ if (! bSig) goto invalid;
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
}
return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
}
if (bExp == 0x7FFF)
{
- if ((Bit64u) (bSig<<1))
- return propagateFloatx80NaN(a, b, status);
+ if (bSig << 1)
+ return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status);
- if (aExp == 0) {
- if (aSig == 0) goto invalid;
- float_raise(status, float_flag_denormal);
+ if (! aExp) {
+ if (! aSig) goto invalid;
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
}
return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
- if (aExp == 0) {
- if (aSig == 0) {
- if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
+ if (! aExp) {
+ if (! aSig) {
+ if (bSig && ! bExp) softfloat_raiseFlags(&status, softfloat_flag_denormal);
return packFloatx80(zSign, 0, 0);
}
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig);
+ aExp = normExpSig.exp + 1;
+ aSig = normExpSig.sig;
}
- if (bExp == 0) {
- if (bSig == 0) return packFloatx80(zSign, 0, 0);
- float_raise(status, float_flag_denormal);
- normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+ if (! bExp) {
+ if (! bSig) return packFloatx80(zSign, 0, 0);
+ softfloat_raiseFlags(&status, softfloat_flag_denormal);
+ struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig);
+ bExp = normExpSig.exp + 1;
+ bSig = normExpSig.sig;
}
- float_raise(status, float_flag_inexact);
+ softfloat_raiseFlags(&status, softfloat_flag_inexact);
if (aSign && aExp >= 0x3FFF)
return a;
if (aExp >= 0x3FFC) // big argument
{
- return fyl2x(floatx80_add(a, floatx80_one, status), b, status);
+ return fyl2x(extF80_add(a, floatx80_one, &status), b, status);
}
// handle tiny argument
if (aExp < FLOATX80_EXP_BIAS-70)
{
// first order approximation, return (a*b)/ln(2)
- Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;
+ int32_t zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;
- mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
- if (0 < (Bit64s) zSig0) {
+ mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
+ if (0 < (int64_t) zSig0) {
shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
--zExp;
}
zExp = zExp + bExp - 0x3FFE;
- mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
- if (0 < (Bit64s) zSig0) {
+ mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
+ if (0 < (int64_t) zSig0) {
shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
--zExp;
}
- return
- roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1, status);
+ return softfloat_roundPackToExtF80(aSign ^ bSign, zExp, zSig0, zSig1, 80, &status);
}
/* ******************************** */
/* using float128 for approximation */
/* ******************************** */
- shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
- float128 x = packFloat128Four(aSign, aExp, zSig0, zSig1);
+ float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status);
+
+ shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
+ float128_t x = packFloat128(aSign, aExp, zSig0, zSig1);
x = poly_l2p1(x, status);
- return floatx80_128_mul(b, x, status);
+ x = f128_mul(x, b128, &status);
+ return f128_to_extF80(x, &status);
}
diff --git a/src/cpu/softfloat3e/i32_to_extF80.cc b/src/cpu/softfloat3e/i32_to_extF80.cc
new file mode 100644
index 0000000000..edd92ced0e
--- /dev/null
+++ b/src/cpu/softfloat3e/i32_to_extF80.cc
@@ -0,0 +1,62 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+extFloat80_t i32_to_extF80(int32_t a)
+{
+ uint16_t uiZ64;
+ uint32_t absA;
+ bool sign;
+ int8_t shiftDist;
+ extFloat80_t z;
+
+ uiZ64 = 0;
+ absA = 0;
+ if (a) {
+ sign = (a < 0);
+ absA = sign ? -(uint32_t) a : (uint32_t) a;
+ shiftDist = softfloat_countLeadingZeros32(absA);
+ uiZ64 = packToExtF80UI64(sign, 0x401E - shiftDist);
+ absA <<= shiftDist;
+ }
+ z.signExp = uiZ64;
+ z.signif = (uint64_t) absA<<32;
+ return z;
+}
diff --git a/src/cpu/softfloat3e/i32_to_f128.cc b/src/cpu/softfloat3e/i32_to_f128.cc
new file mode 100644
index 0000000000..1ae64e46b7
--- /dev/null
+++ b/src/cpu/softfloat3e/i32_to_f128.cc
@@ -0,0 +1,59 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float128_t i32_to_f128(int32_t a)
+{
+ uint64_t uiZ64;
+ bool sign;
+ uint32_t absA;
+ int8_t shiftDist;
+ float128_t z;
+
+ uiZ64 = 0;
+ if (a) {
+ sign = (a < 0);
+ absA = sign ? -(uint32_t) a : (uint32_t) a;
+ shiftDist = softfloat_countLeadingZeros32(absA) + 17;
+ uiZ64 = packToF128UI64(sign, 0x402E - shiftDist, (uint64_t) absA<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float16 i32_to_f16(int32_t a, struct softfloat_status_t *status)
+{
+ bool sign;
+ uint32_t absA;
+ int8_t shiftDist;
+ uint16_t sig;
+
+ sign = (a < 0);
+ absA = sign ? -(uint32_t) a : (uint32_t) a;
+ shiftDist = softfloat_countLeadingZeros32(absA) - 21;
+ if (0 <= shiftDist) {
+ return a ? packToF16UI(sign, 0x18 - shiftDist, (uint16_t) absA<>(-shiftDist) | ((uint32_t) (absA<<(shiftDist & 31)) != 0)
+ : (uint16_t) absA<
+#include
+#include "internals.h"
+#include "softfloat.h"
+
+float32 i32_to_f32(int32_t a, struct softfloat_status_t *status)
+{
+ bool sign;
+ uint32_t absA;
+
+ sign = (a < 0);
+ if (! (a & 0x7FFFFFFF)) {
+ return sign ? packToF32UI(1, 0x9E, 0) : 0;
+ }
+ absA = sign ? -(uint32_t) a : (uint32_t) a;
+ return softfloat_normRoundPackToF32(sign, 0x9C, absA, status);
+}
diff --git a/src/cpu/softfloat3e/i32_to_f64.c b/src/cpu/softfloat3e/i32_to_f64.c
new file mode 100644
index 0000000000..7aaa4e1c28
--- /dev/null
+++ b/src/cpu/softfloat3e/i32_to_f64.c
@@ -0,0 +1,56 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float64 i32_to_f64(int32_t a)
+{
+ bool sign;
+ uint32_t absA;
+ int8_t shiftDist;
+
+ if (! a) {
+ return 0;
+ } else {
+ sign = (a < 0);
+ absA = sign ? -(uint32_t) a : (uint32_t) a;
+ shiftDist = softfloat_countLeadingZeros32(absA) + 21;
+ return packToF64UI(sign, 0x432 - shiftDist, (uint64_t) absA<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+extFloat80_t i64_to_extF80(int64_t a)
+{
+ uint16_t uiZ64;
+ uint64_t absA;
+ bool sign;
+ int8_t shiftDist;
+ extFloat80_t z;
+
+ uiZ64 = 0;
+ absA = 0;
+ if (a) {
+ sign = (a < 0);
+ absA = sign ? -(uint64_t) a : (uint64_t) a;
+ shiftDist = softfloat_countLeadingZeros64(absA);
+ uiZ64 = packToExtF80UI64(sign, 0x403E - shiftDist);
+ absA <<= shiftDist;
+ }
+ z.signExp = uiZ64;
+ z.signif = absA;
+ return z;
+}
diff --git a/src/cpu/softfloat3e/i64_to_f128.cc b/src/cpu/softfloat3e/i64_to_f128.cc
new file mode 100644
index 0000000000..4d80a9e7ab
--- /dev/null
+++ b/src/cpu/softfloat3e/i64_to_f128.cc
@@ -0,0 +1,69 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float128_t i64_to_f128(int64_t a)
+{
+ uint64_t uiZ64, uiZ0;
+ bool sign;
+ uint64_t absA;
+ int8_t shiftDist;
+ struct uint128 zSig;
+ float128_t z;
+
+ if (! a) {
+ uiZ64 = 0;
+ uiZ0 = 0;
+ } else {
+ sign = (a < 0);
+ absA = sign ? -(uint64_t) a : (uint64_t) a;
+ shiftDist = softfloat_countLeadingZeros64(absA) + 49;
+ if (64 <= shiftDist) {
+ zSig.v64 = absA<<(shiftDist - 64);
+ zSig.v0 = 0;
+ } else {
+ zSig = softfloat_shortShiftLeft128(0, absA, shiftDist);
+ }
+ uiZ64 = packToF128UI64(sign, 0x406E - shiftDist, zSig.v64);
+ uiZ0 = zSig.v0;
+ }
+ z.v64 = uiZ64;
+ z.v0 = uiZ0;
+ return z;
+}
diff --git a/src/cpu/softfloat3e/i64_to_f16.c b/src/cpu/softfloat3e/i64_to_f16.c
new file mode 100644
index 0000000000..43873610a4
--- /dev/null
+++ b/src/cpu/softfloat3e/i64_to_f16.c
@@ -0,0 +1,61 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float16 i64_to_f16(int64_t a, struct softfloat_status_t *status)
+{
+ bool sign;
+ uint64_t absA;
+ int8_t shiftDist;
+ uint16_t sig;
+
+ sign = (a < 0);
+ absA = sign ? -(uint64_t) a : (uint64_t) a;
+ shiftDist = softfloat_countLeadingZeros64(absA) - 53;
+ if (0 <= shiftDist) {
+ return a ? packToF16UI(sign, 0x18 - shiftDist, (uint16_t) absA<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float32 i64_to_f32(int64_t a, struct softfloat_status_t *status)
+{
+ bool sign;
+ uint64_t absA;
+ int8_t shiftDist;
+ uint32_t sig;
+
+ sign = (a < 0);
+ absA = sign ? -(uint64_t) a : (uint64_t) a;
+ shiftDist = softfloat_countLeadingZeros64(absA) - 40;
+ if (0 <= shiftDist) {
+ return a ? packToF32UI(sign, 0x95 - shiftDist, (uint32_t) absA<
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "softfloat.h"
+
+float64 i64_to_f64(int64_t a, struct softfloat_status_t *status)
+{
+ bool sign;
+ uint64_t absA;
+
+ sign = (a < 0);
+ if (! (a & UINT64_C(0x7FFFFFFFFFFFFFFF))) {
+ return sign ? packToF64UI(1, 0x43E, 0) : 0;
+ }
+ absA = sign ? -(uint64_t) a : (uint64_t) a;
+ return softfloat_normRoundPackToF64(sign, 0x43C, absA, status);
+}
diff --git a/src/cpu/softfloat3e/internals.h b/src/cpu/softfloat3e/internals.h
new file mode 100644
index 0000000000..3b5d7aa4d5
--- /dev/null
+++ b/src/cpu/softfloat3e/internals.h
@@ -0,0 +1,150 @@
+/*============================================================================
+
+This C header 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.
+
+=============================================================================*/
+
+#ifndef _INTERNALS_H_
+#define _INTERNALS_H_
+
+#include
+#include
+//#include "primitives.h"
+#include "softfloat_types.h"
+
+struct softfloat_status_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+uint32_t softfloat_roundToUI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *);
+uint64_t softfloat_roundToUI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *);
+
+int32_t softfloat_roundToI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *);
+int64_t softfloat_roundToI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *);
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+
+#define signF16UI(a) ((bool) ((uint16_t) (a)>>15))
+#define expF16UI(a) ((int8_t) ((a)>>10) & 0x1F)
+#define fracF16UI(a) ((a) & 0x03FF)
+#define packToF16UI(sign, exp, sig) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))
+
+#define isNaNF16UI(a) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))
+
+struct exp8_sig16 { int8_t exp; uint16_t sig; };
+struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t);
+
+float16 softfloat_roundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *);
+float16 softfloat_normRoundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *);
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF32UI(a) ((bool) ((uint32_t) (a)>>31))
+#define expF32UI(a) ((int16_t) ((a)>>23) & 0xFF)
+#define fracF32UI(a) ((a) & 0x007FFFFF)
+#define packToF32UI(sign, exp, sig) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig))
+
+#define isNaNF32UI(a) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))
+
+struct exp16_sig32 { int16_t exp; uint32_t sig; };
+struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t);
+
+float32 softfloat_roundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *);
+float32 softfloat_normRoundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *);
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF64UI(a) ((bool) ((uint64_t) (a)>>63))
+#define expF64UI(a) ((int16_t) ((a)>>52) & 0x7FF)
+#define fracF64UI(a) ((a) & UINT64_C(0x000FFFFFFFFFFFFF))
+#define packToF64UI(sign, exp, sig) ((uint64_t) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<52) + (sig)))
+
+#define isNaNF64UI(a) (((~(a) & UINT64_C(0x7FF0000000000000)) == 0) && ((a) & UINT64_C(0x000FFFFFFFFFFFFF)))
+
+struct exp16_sig64 { int16_t exp; uint64_t sig; };
+struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t);
+
+float64 softfloat_roundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *);
+float64 softfloat_normRoundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *);
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status);
+extFloat80_t softfloat_subMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status);
+
+#define signExtF80UI64(a64) ((bool) ((uint16_t) (a64)>>15))
+#define expExtF80UI64(a64) ((a64) & 0x7FFF)
+#define packToExtF80UI64(sign, exp) ((uint16_t) (sign)<<15 | (exp))
+
+#define isNaNExtF80UI(a64, a0) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C(0x7FFFFFFFFFFFFFFF)))
+
+extFloat80_t packToExtF80(bool, uint16_t, uint64_t);
+extFloat80_t packToExtF80_twoargs(uint16_t, uint64_t);
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+
+struct exp32_sig64 { int32_t exp; uint64_t sig; };
+struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t);
+
+extFloat80_t
+ softfloat_roundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *);
+extFloat80_t
+ softfloat_normRoundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *);
+
+/*----------------------------------------------------------------------------
+*----------------------------------------------------------------------------*/
+#define signF128UI64(a64) ((bool) ((uint64_t) (a64)>>63))
+#define expF128UI64(a64) ((int32_t) ((a64)>>48) & 0x7FFF)
+#define fracF128UI64(a64) ((a64) & UINT64_C(0x0000FFFFFFFFFFFF))
+#define packToF128UI64(sign, exp, sig64) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<48) + (sig64))
+
+#define isNaNF128UI(a64, a0) (((~(a64) & UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64) & UINT64_C(0x0000FFFFFFFFFFFF))))
+
+struct exp32_sig128 { int32_t exp; struct uint128 sig; };
+struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t, uint64_t);
+
+float128_t
+ softfloat_roundPackToF128(bool, int32_t, uint64_t, uint64_t, uint64_t, struct softfloat_status_t *);
+float128_t
+ softfloat_normRoundPackToF128(bool, int32_t, uint64_t, uint64_t, struct softfloat_status_t *);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/cpu/softfloat3e/isNaN.cc b/src/cpu/softfloat3e/isNaN.cc
new file mode 100644
index 0000000000..8c0bd19122
--- /dev/null
+++ b/src/cpu/softfloat3e/isNaN.cc
@@ -0,0 +1,63 @@
+/*============================================================================
+
+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 "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f16_isNaN(float16 a)
+{
+ return isNaNF16UI(a);
+}
+
+bool f32_isNaN(float32 a)
+{
+ return isNaNF32UI(a);
+}
+
+bool f64_isNaN(float64 a)
+{
+ return isNaNF64UI(a);
+}
+
+bool extF80_isNaN(extFloat80_t a)
+{
+ return isNaNExtF80UI(a.signExp, a.signif);
+}
+
+bool f128_isNaN(float128_t a)
+{
+ return isNaNF128UI(a.v64, a.v0);
+}
diff --git a/src/cpu/softfloat3e/isSignalingNaN.cc b/src/cpu/softfloat3e/isSignalingNaN.cc
new file mode 100644
index 0000000000..994ac37841
--- /dev/null
+++ b/src/cpu/softfloat3e/isSignalingNaN.cc
@@ -0,0 +1,63 @@
+/*============================================================================
+
+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 "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+bool f16_isSignalingNaN(float16 a)
+{
+ return softfloat_isSigNaNF16UI(a);
+}
+
+bool f32_isSignalingNaN(float32 a)
+{
+ return softfloat_isSigNaNF32UI(a);
+}
+
+bool f64_isSignalingNaN(float64 a)
+{
+ return softfloat_isSigNaNF64UI(a);
+}
+
+bool extF80_isSignalingNaN(extFloat80_t a)
+{
+ return softfloat_isSigNaNExtF80UI(a.signExp, a.signif);
+}
+
+bool f128_isSignalingNaN(float128_t a)
+{
+ return softfloat_isSigNaNF128UI(a.v64, a.v0);
+}
diff --git a/src/cpu/softfloat3e/opts-GCC.h b/src/cpu/softfloat3e/opts-GCC.h
new file mode 100644
index 0000000000..dd6c0ab640
--- /dev/null
+++ b/src/cpu/softfloat3e/opts-GCC.h
@@ -0,0 +1,110 @@
+
+/*============================================================================
+
+This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
+Package, Release 3e, by John R. Hauser.
+
+Copyright 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.
+
+=============================================================================*/
+
+#ifndef _OPTS_GCC_H_
+#define _OPTS_GCC_H_
+
+#include
+#include "primitiveTypes.h"
+
+#ifdef SOFTFLOAT_BUILTIN_CLZ
+
+static __inline uint8_t softfloat_countLeadingZeros16(uint16_t a)
+ { return a ? __builtin_clz(a) - 16 : 16; }
+#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
+
+static __inline uint8_t softfloat_countLeadingZeros32(uint32_t a)
+ { return a ? __builtin_clz(a) : 32; }
+#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
+
+static __inline uint8_t softfloat_countLeadingZeros64(uint64_t a)
+ { return a ? __builtin_clzll(a) : 64; }
+#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
+
+#endif
+
+#ifdef SOFTFLOAT_INTRINSIC_INT128
+
+static __inline struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b)
+{
+ union { unsigned __int128 ui; struct uint128 s; } uZ;
+ uZ.ui = (unsigned __int128) a * ((uint64_t) b<<32);
+ return uZ.s;
+}
+#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128
+
+static __inline struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b)
+{
+ union { unsigned __int128 ui; struct uint128 s; } uZ;
+ uZ.ui = (unsigned __int128) a * b;
+ return uZ.s;
+}
+#define softfloat_mul64To128 softfloat_mul64To128
+
+static __inline
+struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b)
+{
+ union { unsigned __int128 ui; struct uint128 s; } uZ;
+ uZ.ui = ((unsigned __int128) a64<<64 | a0) * b;
+ return uZ.s;
+}
+#define softfloat_mul128By32 softfloat_mul128By32
+
+static __inline
+void
+ softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr)
+{
+ unsigned __int128 z0, mid1, mid, z128;
+ z0 = (unsigned __int128) a0 * b0;
+ mid1 = (unsigned __int128) a64 * b0;
+ mid = mid1 + (unsigned __int128) a0 * b64;
+ z128 = (unsigned __int128) a64 * b64;
+ z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64;
+ mid <<= 64;
+ z0 += mid;
+ z128 += (z0 < mid);
+ zPtr[indexWord(4, 0)] = z0;
+ zPtr[indexWord(4, 1)] = z0>>64;
+ zPtr[indexWord(4, 2)] = z128;
+ zPtr[indexWord(4, 3)] = z128>>64;
+}
+#define softfloat_mul128To256M softfloat_mul128To256M
+
+#endif
+
+#endif
+
+#endif
diff --git a/src/cpu/softfloat/softfloat_poly.cc b/src/cpu/softfloat3e/poly.cc
similarity index 84%
rename from src/cpu/softfloat/softfloat_poly.cc
rename to src/cpu/softfloat3e/poly.cc
index 5c7079353e..a89d7f03f8 100644
--- a/src/cpu/softfloat/softfloat_poly.cc
+++ b/src/cpu/softfloat3e/poly.cc
@@ -23,10 +23,10 @@ these four paragraphs for those parts of this code that are retained.
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
-#define FLOAT128
-
#include
+
#include "softfloat.h"
+#include "poly.h"
// 2 3 4 n
// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
@@ -39,13 +39,15 @@ these four paragraphs for those parts of this code that are retained.
// f(x) ~ [ p(x) + x * q(x) ]
//
-float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status)
+float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status)
{
- float128 r = arr[--n];
+ float128_t r = arr[--n];
do {
- r = float128_mul(r, x, status);
- r = float128_add(r, arr[--n], status);
+ r = f128_mulAdd(r, x, arr[--n], 0, status);
+// r = f128_mul(r, x, &status);
+// r = f128_add(r, arr[--n], &status);
+
} while (n > 0);
return r;
@@ -63,9 +65,9 @@ float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *statu
// f(x) ~ [ p(x) + x * q(x) ]
//
-float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status)
+float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status)
{
- return EvalPoly(float128_mul(x, x, status), arr, n, status);
+ return EvalPoly(f128_mul(x, x, &status), arr, n, &status);
}
// 3 5 7 9 2n+1
@@ -83,7 +85,7 @@ float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *statu
// f(x) ~ x * [ p(x) + x * q(x) ]
//
-float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status)
+float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status)
{
- return float128_mul(x, EvenPoly(x, arr, n, status), status);
+ return f128_mul(x, EvenPoly(x, arr, n, status), &status);
}
diff --git a/src/cpu/softfloat3e/poly.h b/src/cpu/softfloat3e/poly.h
new file mode 100644
index 0000000000..1d6c3170c6
--- /dev/null
+++ b/src/cpu/softfloat3e/poly.h
@@ -0,0 +1,43 @@
+/////////////////////////////////////////////////////////////////////////
+// $Id$
+/////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003-2018 Stanislav Shwartsman
+// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+//
+/////////////////////////////////////////////////////////////////////////
+
+#ifndef _POLY_H_
+#define _POLY_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status);
+float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status);
+#else
+float128_t EvenPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status);
+float128_t OddPoly(float128_t x, const float128_t *arr, int n, struct float_status_t *status);
+#endif // __cplusplus
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _POLY_H_
diff --git a/src/cpu/softfloat3e/primitiveTypes.h b/src/cpu/softfloat3e/primitiveTypes.h
new file mode 100644
index 0000000000..67751372f0
--- /dev/null
+++ b/src/cpu/softfloat3e/primitiveTypes.h
@@ -0,0 +1,54 @@
+/*============================================================================
+
+This C header 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.
+
+=============================================================================*/
+
+#ifndef primitiveTypes_h
+#define primitiveTypes_h
+
+/*----------------------------------------------------------------------------
+| These macros are used to isolate the differences in word order between big-
+| endian and little-endian platforms.
+*----------------------------------------------------------------------------*/
+#define wordIncr 1
+#define indexWord(total, n) (n)
+#define indexWordHi(total) ((total) - 1)
+#define indexWordLo(total) 0
+#define indexMultiword(total, m, n) (n)
+#define indexMultiwordHi(total, n) ((total) - (n))
+#define indexMultiwordLo(total, n) 0
+#define indexMultiwordHiBut(total, n) (n)
+#define indexMultiwordLoBut(total, n) 0
+#define INIT_UINTM4(v3, v2, v1, v0) { v0, v1, v2, v3 }
+
+#endif
diff --git a/src/cpu/softfloat3e/primitives.c b/src/cpu/softfloat3e/primitives.c
new file mode 100644
index 0000000000..ba5afb76af
--- /dev/null
+++ b/src/cpu/softfloat3e/primitives.c
@@ -0,0 +1,50 @@
+/*============================================================================
+
+This C header 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 "primitives.h"
+
+/*----------------------------------------------------------------------------
+| This function is the same as 'softfloat_shiftRightJam128Extra' (below),
+| except that 'dist' must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint8_t dist)
+{
+ uint8_t negDist = -dist;
+ struct uint128_extra z;
+ z.v.v64 = a64>>dist;
+ z.v.v0 = a64<<(negDist & 63) | a0>>dist;
+ z.extra = a0<<(negDist & 63) | (extra != 0);
+ return z;
+}
diff --git a/src/cpu/softfloat3e/primitives.h b/src/cpu/softfloat3e/primitives.h
new file mode 100644
index 0000000000..3c811838e7
--- /dev/null
+++ b/src/cpu/softfloat3e/primitives.h
@@ -0,0 +1,527 @@
+/*============================================================================
+
+This C header 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.
+
+=============================================================================*/
+
+#ifndef _PRIMITIVES_H_
+#define _PRIMITIVES_H_
+
+#include
+#include
+#include "softfloat_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SOFTFLOAT_FAST_DIV64TO32
+
+#ifndef softfloat_shortShiftRightJam64
+/*----------------------------------------------------------------------------
+| Shifts 'a' right by the number of bits given in 'dist', which must be in
+| the range 1 to 63. If any nonzero bits are shifted off, they are "jammed"
+| into the least-significant bit of the shifted value by setting the least-
+| significant bit to 1. This shifted-and-jammed value is returned.
+*----------------------------------------------------------------------------*/
+static __inline
+uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint8_t dist)
+{
+ return a>>dist | ((a & (((uint64_t) 1<>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
+}
+#endif
+
+#ifndef softfloat_shiftRightJam64
+/*----------------------------------------------------------------------------
+| Shifts 'a' right by the number of bits given in 'dist', which must not
+| be zero. If any nonzero bits are shifted off, they are "jammed" into the
+| least-significant bit of the shifted value by setting the least-significant
+| bit to 1. This shifted-and-jammed value is returned.
+| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
+| greater than 64, the result will be either 0 or 1, depending on whether 'a'
+| is zero or nonzero.
+*----------------------------------------------------------------------------*/
+static __inline uint64_t softfloat_shiftRightJam64(uint64_t a, uint32_t dist)
+{
+ return (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| A constant table that translates an 8-bit unsigned integer (the array index)
+| into the number of leading 0 bits before the most-significant 1 of that
+| integer. For integer zero (index 0), the corresponding table element is 8.
+*----------------------------------------------------------------------------*/
+extern const uint_least8_t softfloat_countLeadingZeros8[256];
+
+#ifndef softfloat_countLeadingZeros16
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| 'a'. If 'a' is zero, 16 is returned.
+*----------------------------------------------------------------------------*/
+static __inline uint8_t softfloat_countLeadingZeros16(uint16_t a)
+{
+ uint8_t count = 8;
+ if (0x100 <= a) {
+ count = 0;
+ a >>= 8;
+ }
+ count += softfloat_countLeadingZeros8[a];
+ return count;
+}
+#endif
+
+#ifndef softfloat_countLeadingZeros32
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| 'a'. If 'a' is zero, 32 is returned.
+*----------------------------------------------------------------------------*/
+static __inline uint8_t softfloat_countLeadingZeros32(uint32_t a)
+{
+ uint8_t count = 0;
+ if (a < 0x10000) {
+ count = 16;
+ a <<= 16;
+ }
+ if (a < 0x1000000) {
+ count += 8;
+ a <<= 8;
+ }
+ count += softfloat_countLeadingZeros8[a>>24];
+ return count;
+}
+#endif
+
+#ifndef softfloat_countLeadingZeros64
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| 'a'. If 'a' is zero, 64 is returned.
+*----------------------------------------------------------------------------*/
+uint8_t softfloat_countLeadingZeros64(uint64_t a);
+#endif
+
+extern const uint16_t softfloat_approxRecip_1k0s[16];
+extern const uint16_t softfloat_approxRecip_1k1s[16];
+
+#ifndef softfloat_approxRecip32_1
+/*----------------------------------------------------------------------------
+| Returns an approximation to the reciprocal of the number represented by 'a',
+| where 'a' is interpreted as an unsigned fixed-point number with one integer
+| bit and 31 fraction bits. The 'a' input must be "normalized", meaning that
+| its most-significant bit (bit 31) must be 1. Thus, if A is the value of
+| the fixed-point interpretation of 'a', then 1 <= A < 2. The returned value
+| is interpreted as a pure unsigned fraction, having no integer bits and 32
+| fraction bits. The approximation returned is never greater than the true
+| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp
+| (units in the last place).
+*----------------------------------------------------------------------------*/
+#ifdef SOFTFLOAT_FAST_DIV64TO32
+#define softfloat_approxRecip32_1(a) ((uint32_t) (UINT64_C(0x7FFFFFFFFFFFFFFF) / (uint32_t) (a)))
+#endif
+#endif
+
+extern const uint16_t softfloat_approxRecipSqrt_1k0s[16];
+extern const uint16_t softfloat_approxRecipSqrt_1k1s[16];
+
+/*----------------------------------------------------------------------------
+| Returns an approximation to the reciprocal of the square root of the number
+| represented by 'a', where 'a' is interpreted as an unsigned fixed-point
+| number either with one integer bit and 31 fraction bits or with two integer
+| bits and 30 fraction bits. The format of 'a' is determined by 'oddExpA',
+| which must be either 0 or 1. If 'oddExpA' is 1, 'a' is interpreted as
+| having one integer bit, and if 'oddExpA' is 0, 'a' is interpreted as having
+| two integer bits. The 'a' input must be "normalized", meaning that its
+| most-significant bit (bit 31) must be 1. Thus, if A is the value of the
+| fixed-point interpretation of 'a', it follows that 1 <= A < 2 when 'oddExpA'
+| is 1, and 2 <= A < 4 when 'oddExpA' is 0.
+| The returned value is interpreted as a pure unsigned fraction, having
+| no integer bits and 32 fraction bits. The approximation returned is never
+| greater than the true reciprocal 1/sqrt(A), and it differs from the true
+| reciprocal by at most 2.06 ulp (units in the last place). The approximation
+| returned is also always within the range 0.5 to 1; thus, the most-
+| significant bit of the result is always set.
+*----------------------------------------------------------------------------*/
+uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a);
+
+/*----------------------------------------------------------------------------
+| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
+| and 'a0' is equal to the 128-bit unsigned integer formed by concatenating
+| 'b64' and 'b0'.
+*----------------------------------------------------------------------------*/
+static __inline
+bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
+{
+ return (a64 == b64) && (a0 == b0);
+}
+
+/*----------------------------------------------------------------------------
+| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
+| and 'a0' is less than or equal to the 128-bit unsigned integer formed by
+| concatenating 'b64' and 'b0'.
+*----------------------------------------------------------------------------*/
+static __inline
+bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
+{
+ return (a64 < b64) || ((a64 == b64) && (a0 <= b0));
+}
+
+/*----------------------------------------------------------------------------
+| Returns true if the 128-bit unsigned integer formed by concatenating 'a64'
+| and 'a0' is less than the 128-bit unsigned integer formed by concatenating
+| 'b64' and 'b0'.
+*----------------------------------------------------------------------------*/
+static __inline
+bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
+{
+ return (a64 < b64) || ((a64 == b64) && (a0 < b0));
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' left by the
+| number of bits given in 'dist', which must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint8_t dist)
+{
+ struct uint128 z;
+ z.v64 = a64<>(-dist & 63);
+ z.v0 = a0<>dist;
+ z.v0 = a64<<(-dist & 63) | a0>>dist;
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| This function is the same as 'softfloat_shiftRightJam64Extra' (below),
+| except that 'dist' must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint8_t dist)
+{
+ struct uint64_extra z;
+ z.v = a>>dist;
+ z.extra = a<<(-dist & 63) | (extra != 0);
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
+| number of bits given in 'dist', which must be in the range 1 to 63. If any
+| nonzero bits are shifted off, they are "jammed" into the least-significant
+| bit of the shifted value by setting the least-significant bit to 1. This
+| shifted-and-jammed value is returned.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint8_t dist)
+{
+ uint8_t negDist = -dist;
+ struct uint128 z;
+ z.v64 = a64>>dist;
+ z.v0 =
+ a64<<(negDist & 63) | a0>>dist
+ | ((uint64_t) (a0<<(negDist & 63)) != 0);
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| This function is the same as 'softfloat_shiftRightJam128Extra' (below),
+| except that 'dist' must be in the range 1 to 63.
+*----------------------------------------------------------------------------*/
+extern struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint8_t dist);
+
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64
+| _plus_ the number of bits given in 'dist', which must not be zero. This
+| shifted value is at most 64 nonzero bits and is returned in the 'v' field
+| of the 'struct uint64_extra' result. The 64-bit 'extra' field of the result
+| contains a value formed as follows from the bits that were shifted off: The
+| _last_ bit shifted off is the most-significant bit of the 'extra' field, and
+| the other 63 bits of the 'extra' field are all zero if and only if _all_but_
+| _the_last_ bits shifted off were all zero.
+| (This function makes more sense if 'a' and 'extra' are considered to form
+| an unsigned fixed-point number with binary point between 'a' and 'extra'.
+| This fixed-point value is shifted right by the number of bits given in
+| 'dist', and the integer part of this shifted value is returned in the 'v'
+| field of the result. The fractional part of the shifted value is modified
+| as described above and returned in the 'extra' field of the result.)
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint64_extra
+ softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint32_t dist)
+{
+ struct uint64_extra z;
+ if (dist < 64) {
+ z.v = a>>dist;
+ z.extra = a<<(-dist & 63);
+ } else {
+ z.v = 0;
+ z.extra = (dist == 64) ? a : (a != 0);
+ }
+ z.extra |= (extra != 0);
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the
+| number of bits given in 'dist', which must not be zero. If any nonzero bits
+| are shifted off, they are "jammed" into the least-significant bit of the
+| shifted value by setting the least-significant bit to 1. This shifted-and-
+| jammed value is returned.
+| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
+| greater than 128, the result will be either 0 or 1, depending on whether the
+| original 128 bits are all zeros.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128
+ softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint32_t dist)
+{
+ uint8_t u8NegDist;
+ struct uint128 z;
+
+ if (dist < 64) {
+ u8NegDist = -dist;
+ z.v64 = a64>>dist;
+ z.v0 =
+ a64<<(u8NegDist & 63) | a0>>dist
+ | ((uint64_t) (a0<<(u8NegDist & 63)) != 0);
+ } else {
+ z.v64 = 0;
+ z.v0 =
+ (dist < 127)
+ ? a64>>(dist & 63)
+ | (((a64 & (((uint64_t) 1<<(dist & 63)) - 1)) | a0)
+ != 0)
+ : ((a64 | a0) != 0);
+ }
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 192 bits formed by concatenating 'a64', 'a0', and 'extra' right
+| by 64 _plus_ the number of bits given in 'dist', which must not be zero.
+| This shifted value is at most 128 nonzero bits and is returned in the 'v'
+| field of the 'struct uint128_extra' result. The 64-bit 'extra' field of the
+| result contains a value formed as follows from the bits that were shifted
+| off: The _last_ bit shifted off is the most-significant bit of the 'extra'
+| field, and the other 63 bits of the 'extra' field are all zero if and only
+| if _all_but_the_last_ bits shifted off were all zero.
+| (This function makes more sense if 'a64', 'a0', and 'extra' are considered
+| to form an unsigned fixed-point number with binary point between 'a0' and
+| 'extra'. This fixed-point value is shifted right by the number of bits
+| given in 'dist', and the integer part of this shifted value is returned
+| in the 'v' field of the result. The fractional part of the shifted value
+| is modified as described above and returned in the 'extra' field of the
+| result.)
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128_extra
+ softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint32_t dist)
+{
+ uint8_t u8NegDist;
+ struct uint128_extra z;
+
+ u8NegDist = -dist;
+ if (dist < 64) {
+ z.v.v64 = a64>>dist;
+ z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist;
+ z.extra = a0<<(u8NegDist & 63);
+ } else {
+ z.v.v64 = 0;
+ if (dist == 64) {
+ z.v.v0 = a64;
+ z.extra = a0;
+ } else {
+ extra |= a0;
+ if (dist < 128) {
+ z.v.v0 = a64>>(dist & 63);
+ z.extra = a64<<(u8NegDist & 63);
+ } else {
+ z.v.v0 = 0;
+ z.extra = (dist == 128) ? a64 : (a64 != 0);
+ }
+ }
+ }
+ z.extra |= (extra != 0);
+ return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 256-bit unsigned integer pointed to by 'aPtr' right by the number
+| of bits given in 'dist', which must not be zero. If any nonzero bits are
+| shifted off, they are "jammed" into the least-significant bit of the shifted
+| value by setting the least-significant bit to 1. This shifted-and-jammed
+| value is stored at the location pointed to by 'zPtr'. Each of 'aPtr' and
+| 'zPtr' points to an array of four 64-bit elements that concatenate in the
+| platform's normal endian order to form a 256-bit integer.
+| The value of 'dist' can be arbitrarily large. In particular, if 'dist'
+| is greater than 256, the stored result will be either 0 or 1, depending on
+| whether the original 256 bits are all zeros.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *zPtr);
+
+#ifndef softfloat_add128
+/*----------------------------------------------------------------------------
+| Returns the sum of the 128-bit integer formed by concatenating 'a64' and
+| 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. The
+| addition is modulo 2^128, so any carry out is lost.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
+{
+ struct uint128 z;
+ z.v0 = a0 + b0;
+ z.v64 = a64 + b64 + (z.v0 < a0);
+ return z;
+}
+#endif
+
+#ifndef softfloat_add256M
+/*----------------------------------------------------------------------------
+| Adds the two 256-bit integers pointed to by 'aPtr' and 'bPtr'. The addition
+| is modulo 2^256, so any carry out is lost. The sum is stored at the
+| location pointed to by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to
+| an array of four 64-bit elements that concatenate in the platform's normal
+| endian order to form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_add256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr);
+#endif
+
+#ifndef softfloat_sub128
+/*----------------------------------------------------------------------------
+| Returns the difference of the 128-bit integer formed by concatenating 'a64'
+| and 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'.
+| The subtraction is modulo 2^128, so any borrow out (carry out) is lost.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
+{
+ struct uint128 z;
+ z.v0 = a0 - b0;
+ z.v64 = a64 - b64;
+ z.v64 -= (a0 < b0);
+ return z;
+}
+#endif
+
+#ifndef softfloat_sub256M
+/*----------------------------------------------------------------------------
+| Subtracts the 256-bit integer pointed to by 'bPtr' from the 256-bit integer
+| pointed to by 'aPtr'. The addition is modulo 2^256, so any borrow out
+| (carry out) is lost. The difference is stored at the location pointed to
+| by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to an array of four
+| 64-bit elements that concatenate in the platform's normal endian order to
+| form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_sub256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr);
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns the 128-bit product of 'a', 'b', and 2^32.
+*----------------------------------------------------------------------------*/
+static __inline struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b)
+{
+ uint64_t mid;
+ struct uint128 z;
+ mid = (uint64_t) (uint32_t) a * b;
+ z.v0 = mid<<32;
+ z.v64 = (uint64_t) (uint32_t) (a>>32) * b + (mid>>32);
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| Returns the 128-bit product of 'a' and 'b'.
+*----------------------------------------------------------------------------*/
+struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b);
+
+/*----------------------------------------------------------------------------
+| Returns the product of the 128-bit integer formed by concatenating 'a64' and
+| 'a0', multiplied by 'b'. The multiplication is modulo 2^128; any overflow
+| bits are discarded.
+*----------------------------------------------------------------------------*/
+static __inline
+struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b)
+{
+ struct uint128 z;
+ uint64_t mid;
+ uint32_t carry;
+ z.v0 = a0 * b;
+ mid = (uint64_t) (uint32_t) (a0>>32) * b;
+ carry = (uint32_t) ((uint32_t) (z.v0>>32) - (uint32_t) mid);
+ z.v64 = a64 * b + (uint32_t) ((mid + carry)>>32);
+ return z;
+}
+
+/*----------------------------------------------------------------------------
+| Multiplies the 128-bit unsigned integer formed by concatenating 'a64' and
+| 'a0' by the 128-bit unsigned integer formed by concatenating 'b64' and
+| 'b0'. The 256-bit product is stored at the location pointed to by 'zPtr'.
+| Argument 'zPtr' points to an array of four 64-bit elements that concatenate
+| in the platform's normal endian order to form a 256-bit integer.
+*----------------------------------------------------------------------------*/
+void
+ softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _PRIMITIVES_H_
diff --git a/src/cpu/softfloat3e/s_add128.cc b/src/cpu/softfloat3e/s_add128.cc
new file mode 100644
index 0000000000..8efabb8501
--- /dev/null
+++ b/src/cpu/softfloat3e/s_add128.cc
@@ -0,0 +1,51 @@
+/*============================================================================
+
+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
+#include "softfloat_types.h"
+
+#ifndef softfloat_add128
+
+struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0)
+{
+ struct uint128 z;
+
+ z.v0 = a0 + b0;
+ z.v64 = a64 + b64 + (z.v0 < a0);
+ return z;
+}
+
+#endif
+
diff --git a/src/cpu/softfloat3e/s_add256M.c b/src/cpu/softfloat3e/s_add256M.c
new file mode 100644
index 0000000000..32fdf122f5
--- /dev/null
+++ b/src/cpu/softfloat3e/s_add256M.c
@@ -0,0 +1,60 @@
+/*============================================================================
+
+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
+#include "primitiveTypes.h"
+
+#ifndef softfloat_add256M
+
+void softfloat_add256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr)
+{
+ unsigned int index;
+ uint8_t carry;
+ uint64_t wordA, wordZ;
+
+ index = indexWordLo(4);
+ carry = 0;
+ for (;;) {
+ wordA = aPtr[index];
+ wordZ = wordA + bPtr[index] + carry;
+ zPtr[index] = wordZ;
+ if (index == indexWordHi(4)) break;
+ if (wordZ != wordA) carry = (wordZ < wordA);
+ index += wordIncr;
+ }
+}
+
+#endif
+
diff --git a/src/cpu/softfloat3e/s_addMagsExtF80.cc b/src/cpu/softfloat3e/s_addMagsExtF80.cc
new file mode 100644
index 0000000000..5cc969198b
--- /dev/null
+++ b/src/cpu/softfloat3e/s_addMagsExtF80.cc
@@ -0,0 +1,146 @@
+/*============================================================================
+
+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
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status)
+{
+ int32_t expA;
+ uint64_t sigA;
+ int32_t expB;
+ uint64_t sigB;
+ int32_t expDiff;
+ uint64_t sigZ, sigZExtra;
+ struct exp32_sig64 normExpSig;
+ int32_t expZ;
+ struct uint64_extra sig64Extra;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expA = expExtF80UI64(uiA64);
+ sigA = uiA0;
+ expB = expExtF80UI64(uiB64);
+ sigB = uiB0;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expA == 0x7FFF) {
+ if ((sigA << 1) || ((expB == 0x7FFF) && (sigB << 1)))
+ goto propagateNaN;
+ if (sigB && ! expB)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToExtF80_twoargs(uiA64, uiA0);
+ }
+ if (expB == 0x7FFF) {
+ if (sigB << 1) goto propagateNaN;
+ if (sigA && ! expA)
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000));
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (! expA) {
+ if (! sigA) {
+ if (! expB && sigB) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB = normExpSig.exp + 1;
+ sigB = normExpSig.sig;
+ }
+ expZ = expB;
+ sigZ = sigB;
+ sigZExtra = 0;
+ goto roundAndPack;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
+ expA = normExpSig.exp + 1;
+ sigA = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expB == 0) {
+ if (sigB == 0) {
+ expZ = expA;
+ sigZ = sigA;
+ sigZExtra = 0;
+ goto roundAndPack;
+ }
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
+ expB = normExpSig.exp + 1;
+ sigB = normExpSig.sig;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expA - expB;
+ if (! expDiff) {
+ sigZ = sigA + sigB;
+ sigZExtra = 0;
+ expZ = expA;
+ goto shiftRight1;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (expDiff < 0) {
+ expZ = expB;
+ sig64Extra = softfloat_shiftRightJam64Extra(sigA, 0, -expDiff);
+ sigA = sig64Extra.v;
+ sigZExtra = sig64Extra.extra;
+ } else {
+ expZ = expA;
+ sig64Extra = softfloat_shiftRightJam64Extra(sigB, 0, expDiff);
+ sigB = sig64Extra.v;
+ sigZExtra = sig64Extra.extra;
+ }
+ sigZ = sigA + sigB;
+ if (sigZ & UINT64_C(0x8000000000000000)) goto roundAndPack;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ shiftRight1:
+ sig64Extra = softfloat_shortShiftRightJam64Extra(sigZ, sigZExtra, 1);
+ sigZ = sig64Extra.v | UINT64_C(0x8000000000000000);
+ sigZExtra = sig64Extra.extra;
+ ++expZ;
+ roundAndPack:
+ return softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
+}
diff --git a/src/cpu/softfloat3e/s_addMagsF128.cc b/src/cpu/softfloat3e/s_addMagsF128.cc
new file mode 100644
index 0000000000..b831796cc4
--- /dev/null
+++ b/src/cpu/softfloat3e/s_addMagsF128.cc
@@ -0,0 +1,138 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+
+float128_t softfloat_addMagsF128(uint64_t uiA64, uint64_t uiA0, uint64_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status)
+{
+ int32_t expA;
+ struct uint128 sigA;
+ int32_t expB;
+ struct uint128 sigB;
+ int32_t expDiff;
+ struct uint128 uiZ, sigZ;
+ int32_t expZ;
+ uint64_t sigZExtra;
+ struct uint128_extra sig128Extra;
+
+ 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;
+ return 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;
+ return 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;
+ return 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;
+ return 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(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status);
+ propagateNaN:
+ uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
+ return uiZ;
+}
diff --git a/src/cpu/softfloat3e/s_addMagsF16.c b/src/cpu/softfloat3e/s_addMagsF16.c
new file mode 100644
index 0000000000..022f254a80
--- /dev/null
+++ b/src/cpu/softfloat3e/s_addMagsF16.c
@@ -0,0 +1,192 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "specialize.h"
+#include "softfloat.h"
+
+float16 softfloat_addMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status)
+{
+ int8_t expA;
+ uint16_t sigA;
+ int8_t expB;
+ uint16_t sigB;
+ int8_t expDiff;
+ uint16_t uiZ;
+ bool signZ;
+ int8_t expZ;
+ uint16_t sigZ;
+ uint16_t sigX, sigY;
+ int8_t shiftDist;
+ uint32_t sig32Z;
+ int8_t roundingMode;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expA = expF16UI(uiA);
+ sigA = fracF16UI(uiA);
+ expB = expF16UI(uiB);
+ sigB = fracF16UI(uiB);
+ signZ = signF16UI(uiA);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) {
+ sigA = 0;
+ uiA = packToF16UI(signZ, 0, 0);
+ }
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expA - expB;
+ if (! expDiff) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (! expA) {
+ uiZ = uiA + sigB;
+ if (sigA | sigB) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ bool isTiny = (expF16UI(uiZ) == 0);
+ if (isTiny) {
+ if (softfloat_flushUnderflowToZero(status)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
+ return packToF16UI(signZ, 0, 0);
+ }
+ if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow);
+ }
+ }
+ }
+ return uiZ;
+ }
+ if (expA == 0x1F) {
+ if (sigA | sigB) goto propagateNaN;
+ return uiA;
+ }
+ expZ = expA;
+ sigZ = 0x0800 + sigA + sigB;
+ if (! (sigZ & 1) && (expZ < 0x1E)) {
+ sigZ >>= 1;
+ goto pack;
+ }
+ sigZ <<= 3;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (expDiff < 0) {
+ /*----------------------------------------------------------------
+ *----------------------------------------------------------------*/
+ if (expB == 0x1F) {
+ if (sigB) goto propagateNaN;
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToF16UI(signZ, 0x1F, 0);
+ }
+
+ if ((!expA && sigA) || (!expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+
+ if (expDiff <= -13) {
+ uiZ = packToF16UI(signZ, expB, sigB);
+ if (expA | sigA) goto addEpsilon;
+ return uiZ;
+ }
+ expZ = expB;
+ sigX = sigB | 0x0400;
+ sigY = sigA + (expA ? 0x0400 : sigA);
+ shiftDist = 19 + expDiff;
+ } else {
+ /*----------------------------------------------------------------
+ *----------------------------------------------------------------*/
+ uiZ = uiA;
+ if (expA == 0x1F) {
+ if (sigA) goto propagateNaN;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return uiZ;
+ }
+
+ if ((!expA && sigA) || (!expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+
+ if (13 <= expDiff) {
+ if (expB | sigB) goto addEpsilon;
+ return uiZ;
+ }
+ expZ = expA;
+ sigX = sigA | 0x0400;
+ sigY = sigB + (expB ? 0x0400 : sigB);
+ shiftDist = 19 - expDiff;
+ }
+ sig32Z = ((uint32_t) sigX<<19) + ((uint32_t) sigY<>16;
+ if (sig32Z & 0xFFFF) {
+ sigZ |= 1;
+ } else {
+ if (! (sigZ & 0xF) && (expZ < 0x1E)) {
+ sigZ >>= 4;
+ goto pack;
+ }
+ }
+ }
+ return softfloat_roundPackToF16(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF16UI(uiA, uiB, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ addEpsilon:
+ roundingMode = softfloat_getRoundingMode(status);
+ if (roundingMode != softfloat_round_near_even) {
+ if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) {
+ ++uiZ;
+ if ((uint16_t) (uiZ<<1) == 0xF800) {
+ softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact);
+ }
+ }
+ }
+ softfloat_raiseFlags(status, softfloat_flag_inexact);
+ return uiZ;
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ pack:
+ return packToF16UI(signZ, expZ, sigZ);
+}
diff --git a/src/cpu/softfloat3e/s_addMagsF32.c b/src/cpu/softfloat3e/s_addMagsF32.c
new file mode 100644
index 0000000000..df902348a4
--- /dev/null
+++ b/src/cpu/softfloat3e/s_addMagsF32.c
@@ -0,0 +1,147 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+
+float32 softfloat_addMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status)
+{
+ int16_t expA;
+ uint32_t sigA;
+ int16_t expB;
+ uint32_t sigB;
+ int16_t expDiff;
+ uint32_t uiZ;
+ bool signZ;
+ int16_t expZ;
+ uint32_t sigZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expA = expF32UI(uiA);
+ sigA = fracF32UI(uiA);
+ expB = expF32UI(uiB);
+ sigB = fracF32UI(uiB);
+ signZ = signF32UI(uiA);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) {
+ sigA = 0;
+ uiA = packToF32UI(signZ, 0, 0);
+ }
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expA - expB;
+ if (! expDiff) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (! expA) {
+ uiZ = uiA + sigB;
+ if (sigA | sigB) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ bool isTiny = (expF32UI(uiZ) == 0);
+ if (isTiny) {
+ if (softfloat_flushUnderflowToZero(status)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
+ return packToF32UI(signZ, 0, 0);
+ }
+ if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow);
+ }
+ }
+ }
+ return uiZ;
+ }
+ if (expA == 0xFF) {
+ if (sigA | sigB) goto propagateNaN;
+ return uiA;
+ }
+ expZ = expA;
+ sigZ = 0x01000000 + sigA + sigB;
+ if (! (sigZ & 1) && (expZ < 0xFE)) {
+ return packToF32UI(signZ, expZ, sigZ>>1);
+ }
+ sigZ <<= 6;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ signZ = signF32UI(uiA);
+ sigA <<= 6;
+ sigB <<= 6;
+ if (expDiff < 0) {
+ if (expB == 0xFF) {
+ if (sigB) goto propagateNaN;
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToF32UI(signZ, 0xFF, 0);
+ }
+
+ if ((!expA && sigA) || (!expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+
+ expZ = expB;
+ sigA += expA ? 0x20000000 : sigA;
+ sigA = softfloat_shiftRightJam32(sigA, -expDiff);
+ } else {
+ if (expA == 0xFF) {
+ if (sigA) goto propagateNaN;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return uiA;
+ }
+
+ if ((!expA && sigA) || (!expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+
+ expZ = expA;
+ sigB += expB ? 0x20000000 : sigB;
+ sigB = softfloat_shiftRightJam32(sigB, expDiff);
+ }
+ sigZ = 0x20000000 + sigA + sigB;
+ if (sigZ < 0x40000000) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ }
+ return softfloat_roundPackToF32(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF32UI(uiA, uiB, status);
+}
diff --git a/src/cpu/softfloat3e/s_addMagsF64.c b/src/cpu/softfloat3e/s_addMagsF64.c
new file mode 100644
index 0000000000..a315860f6c
--- /dev/null
+++ b/src/cpu/softfloat3e/s_addMagsF64.c
@@ -0,0 +1,149 @@
+/*============================================================================
+
+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
+#include
+#include "internals.h"
+#include "primitives.h"
+#include "specialize.h"
+
+float64 softfloat_addMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status)
+{
+ int16_t expA;
+ uint64_t sigA;
+ int16_t expB;
+ uint64_t sigB;
+ int16_t expDiff;
+ uint64_t uiZ;
+ int16_t expZ;
+ uint64_t sigZ;
+
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expA = expF64UI(uiA);
+ sigA = fracF64UI(uiA);
+ expB = expF64UI(uiB);
+ sigB = fracF64UI(uiB);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ if (softfloat_denormalsAreZeros(status)) {
+ if (!expA) {
+ sigA = 0;
+ uiA = packToF64UI(signZ, 0, 0);
+ }
+ if (!expB) sigB = 0;
+ }
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ expDiff = expA - expB;
+ if (! expDiff) {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ if (! expA) {
+ uiZ = uiA + sigB;
+ if (sigA | sigB) {
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+ bool isTiny = (expF64UI(uiZ) == 0);
+ if (isTiny) {
+ if (softfloat_flushUnderflowToZero(status)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
+ return packToF64UI(signZ, 0, 0);
+ }
+ if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) {
+ softfloat_raiseFlags(status, softfloat_flag_underflow);
+ }
+ }
+ }
+ return uiZ;
+ }
+ if (expA == 0x7FF) {
+ if (sigA | sigB) goto propagateNaN;
+ return uiA;
+ }
+ expZ = expA;
+ sigZ = UINT64_C(0x0020000000000000) + sigA + sigB;
+ sigZ <<= 9;
+ } else {
+ /*--------------------------------------------------------------------
+ *--------------------------------------------------------------------*/
+ sigA <<= 9;
+ sigB <<= 9;
+ if (expDiff < 0) {
+ if (expB == 0x7FF) {
+ if (sigB) goto propagateNaN;
+ if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return packToF64UI(signZ, 0x7FF, 0);
+ }
+
+ if ((!expA && sigA) || (!expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+
+ expZ = expB;
+ if (expA) {
+ sigA += UINT64_C(0x2000000000000000);
+ } else {
+ sigA <<= 1;
+ }
+ sigA = softfloat_shiftRightJam64(sigA, -expDiff);
+ } else {
+ if (expA == 0x7FF) {
+ if (sigA) goto propagateNaN;
+ if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
+ return uiA;
+ }
+
+ if ((!expA && sigA) || (!expB && sigB))
+ softfloat_raiseFlags(status, softfloat_flag_denormal);
+
+ expZ = expA;
+ if (expB) {
+ sigB += UINT64_C(0x2000000000000000);
+ } else {
+ sigB <<= 1;
+ }
+ sigB = softfloat_shiftRightJam64(sigB, expDiff);
+ }
+ sigZ = UINT64_C(0x2000000000000000) + sigA + sigB;
+ if (sigZ < UINT64_C(0x4000000000000000)) {
+ --expZ;
+ sigZ <<= 1;
+ }
+ }
+ return softfloat_roundPackToF64(signZ, expZ, sigZ, status);
+ /*------------------------------------------------------------------------
+ *------------------------------------------------------------------------*/
+ propagateNaN:
+ return softfloat_propagateNaNF64UI(uiA, uiB, status);
+}
diff --git a/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c b/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c
new file mode 100644
index 0000000000..776c146ef3
--- /dev/null
+++ b/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c
@@ -0,0 +1,63 @@
+/*============================================================================
+
+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