mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 20:35:32 -07:00
Merge remote-tracking branch 'upstream/master' into feature/ich2
This commit is contained in:
@@ -59,6 +59,7 @@ AppDir:
|
||||
- libqt5widgets5 # if QT:BOOL=ON
|
||||
- libsixel1 # if CLI:BOOL=ON
|
||||
- libslirp0
|
||||
- libsndfile1
|
||||
- libsndio7.0 # if OPENAL:BOOL=ON
|
||||
- libvdeplug-dev # -dev also pulls in libvdeplug2. -dev is required to get the proper .so symlink to the library
|
||||
- libx11-6 # if QT:BOOL=ON
|
||||
|
||||
@@ -605,7 +605,7 @@ else
|
||||
# ...and the ones we do want listed. Non-dev packages fill missing spots on the list.
|
||||
libpkgs=""
|
||||
longest_libpkg=0
|
||||
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev
|
||||
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev libsndfile1-dev
|
||||
do
|
||||
libpkgs="$libpkgs $pkg:$arch_deb"
|
||||
length=$(echo -n $pkg | sed 's/-dev$//' | sed "s/qtdeclarative/qt/" | wc -c)
|
||||
|
||||
@@ -15,3 +15,4 @@ fluidsynth
|
||||
ghostscript
|
||||
libslirp
|
||||
vde2
|
||||
libsndfile
|
||||
|
||||
@@ -12,3 +12,5 @@ libslirp
|
||||
fluidsynth
|
||||
qt5-static
|
||||
qt5-translations
|
||||
vulkan-headers
|
||||
libsndfile
|
||||
|
||||
@@ -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
|
||||
|
||||
16
.gitattributes
vendored
16
.gitattributes
vendored
@@ -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.
|
||||
|
||||
115
.github/workflows/c-cpp.yml
vendored
115
.github/workflows/c-cpp.yml
vendored
@@ -1,115 +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
|
||||
|
||||
- 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
|
||||
12
.github/workflows/cmake_linux.yml
vendored
12
.github/workflows/cmake_linux.yml
vendored
@@ -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*"
|
||||
|
||||
@@ -40,10 +40,10 @@ jobs:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
- name: Debug
|
||||
preset: debug
|
||||
preset: dev_debug
|
||||
slug: -Debug
|
||||
- name: Dev
|
||||
preset: experimental
|
||||
preset: development
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
@@ -88,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: >-
|
||||
@@ -115,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/**
|
||||
|
||||
113
.github/workflows/cmake_macos.yml
vendored
113
.github/workflows/cmake_macos.yml
vendored
@@ -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*"
|
||||
|
||||
@@ -40,10 +40,10 @@ jobs:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
- name: Debug
|
||||
preset: debug
|
||||
preset: dev_debug
|
||||
slug: -Debug
|
||||
- name: Dev
|
||||
preset: experimental
|
||||
preset: development
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
@@ -76,9 +76,7 @@ jobs:
|
||||
run: >-
|
||||
brew install
|
||||
ninja
|
||||
freetype
|
||||
sdl2
|
||||
libpng
|
||||
rtmidi
|
||||
openal-soft
|
||||
fluidsynth
|
||||
@@ -90,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: >-
|
||||
@@ -120,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: dev_debug
|
||||
slug: -Debug
|
||||
- name: Dev
|
||||
preset: development
|
||||
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/**
|
||||
|
||||
163
.github/workflows/cmake_windows_llvm.yml
vendored
163
.github/workflows/cmake_windows_llvm.yml
vendored
@@ -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/**
|
||||
27
.github/workflows/cmake_windows_msys2.yml
vendored
27
.github/workflows/cmake_windows_msys2.yml
vendored
@@ -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*"
|
||||
|
||||
@@ -44,10 +44,10 @@ jobs:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
- name: Debug
|
||||
preset: debug
|
||||
preset: dev_debug
|
||||
slug: -Debug
|
||||
- name: Dev
|
||||
preset: experimental
|
||||
preset: development
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
@@ -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
|
||||
@@ -112,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: >-
|
||||
@@ -139,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/**
|
||||
|
||||
10
.github/workflows/codeql_linux.yml
vendored
10
.github/workflows/codeql_linux.yml
vendored
@@ -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*"
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
# preset: debug
|
||||
# slug: -Debug
|
||||
- name: Dev
|
||||
preset: experimental
|
||||
preset: dev_debug
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
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
|
||||
@@ -106,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}}"
|
||||
|
||||
12
.github/workflows/codeql_macos.yml
vendored
12
.github/workflows/codeql_macos.yml
vendored
@@ -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*"
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
# preset: debug
|
||||
# slug: -Debug
|
||||
- name: Dev
|
||||
preset: experimental
|
||||
preset: dev_debug
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
@@ -70,9 +70,7 @@ jobs:
|
||||
run: >-
|
||||
brew install
|
||||
ninja
|
||||
freetype
|
||||
sdl2
|
||||
libpng
|
||||
rtmidi
|
||||
openal-soft
|
||||
fluidsynth
|
||||
@@ -82,7 +80,7 @@ jobs:
|
||||
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
|
||||
@@ -102,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}}"
|
||||
|
||||
14
.github/workflows/codeql_windows_msys2.yml
vendored
14
.github/workflows/codeql_windows_msys2.yml
vendored
@@ -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*"
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
# preset: debug
|
||||
# slug: -Debug
|
||||
- name: Dev
|
||||
preset: experimental
|
||||
preset: dev_debug
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
@@ -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
|
||||
@@ -116,7 +114,7 @@ jobs:
|
||||
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
|
||||
@@ -135,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}}"
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -59,3 +59,6 @@ CMakeLists.txt.user
|
||||
|
||||
# MacOS Finder stuff
|
||||
.DS_Store
|
||||
|
||||
# clangd
|
||||
.cache
|
||||
|
||||
@@ -35,7 +35,7 @@ if(MUNT_EXTERNAL)
|
||||
endif()
|
||||
|
||||
project(86Box
|
||||
VERSION 4.1
|
||||
VERSION 4.2.1
|
||||
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,7 @@ 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(G100 "Matrox Productiva G100" 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)
|
||||
@@ -156,9 +161,8 @@ cmake_dependent_option(LASERXT "VTech Laser XT"
|
||||
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(PCL "Generic PCL5e Printer" 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
|
||||
|
||||
@@ -43,17 +43,15 @@
|
||||
"name": "development",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"DEV_BRANCH": "ON",
|
||||
"NEW_DYNAREC": "OFF"
|
||||
"DEV_BRANCH": "ON"
|
||||
},
|
||||
"inherits": "base"
|
||||
},
|
||||
{
|
||||
"name": "experimental",
|
||||
"name": "dev_debug",
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"DEV_BRANCH": "ON",
|
||||
"NEW_DYNAREC": "ON"
|
||||
"DEV_BRANCH": "ON"
|
||||
},
|
||||
"inherits": "base"
|
||||
},
|
||||
|
||||
@@ -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.
|
||||
|
||||
18
SECURITY.md
Normal file
18
SECURITY.md
Normal file
@@ -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.
|
||||
@@ -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'/'
|
||||
|
||||
4
debian/changelog
vendored
4
debian/changelog
vendored
@@ -1,5 +1,5 @@
|
||||
86box (4.1) UNRELEASED; urgency=medium
|
||||
86box (4.2.1) UNRELEASED; urgency=medium
|
||||
|
||||
* Bump release.
|
||||
|
||||
-- Jasmine Iwanek <jriwanek@gmail.com> Mon, 16 Oct 2023 20:24:46 +0200
|
||||
-- Jasmine Iwanek <jriwanek@gmail.com> Fri, 26 Jul 2024 21:09:16 +0200
|
||||
|
||||
3
debian/control
vendored
3
debian/control
vendored
@@ -13,6 +13,7 @@ Build-Depends: cmake (>= 3.21),
|
||||
libsdl2-dev,
|
||||
libslirp-dev,
|
||||
libxkbcommon-x11-dev,
|
||||
libsndfile-dev,
|
||||
ninja-build,
|
||||
qttools5-dev,
|
||||
qtbase5-private-dev
|
||||
@@ -31,4 +32,4 @@ Recommends: libpcap0.8-dev
|
||||
Description: An emulator for classic IBM PC clones
|
||||
86Box is a low level x86 emulator that runs older operating systems and software
|
||||
designed for IBM PC systems and compatibles from 1981 through
|
||||
fairly recent system designs based on the PCI bus.
|
||||
fairly recent system designs based on the PCI bus.
|
||||
|
||||
84
src/86box.c
84
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>
|
||||
@@ -170,17 +171,19 @@ int video_filter_method = 1; /* (C) video *
|
||||
int video_vsync = 0; /* (C) video */
|
||||
int video_framerate = -1; /* (C) video */
|
||||
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 */
|
||||
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 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 */
|
||||
int isartc_type = 0; /* (C) enable ISA RTC card */
|
||||
int gfxcard[2] = { 0, 0 }; /* (C) graphics/video card */
|
||||
int gfxcard[GFXCARD_MAX] = { 0, 0 }; /* (C) graphics/video card */
|
||||
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;
|
||||
@@ -345,12 +354,14 @@ fatal(const char *fmt, ...)
|
||||
if ((sp = strchr(temp, '\n')) != NULL)
|
||||
*sp = '\0';
|
||||
|
||||
do_pause(2);
|
||||
|
||||
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
|
||||
|
||||
/* Cleanly terminate all of the emulator's components so as
|
||||
to avoid things like threads getting stuck. */
|
||||
do_stop();
|
||||
|
||||
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
|
||||
|
||||
fflush(stdlog);
|
||||
|
||||
exit(-1);
|
||||
@@ -387,12 +398,14 @@ fatal_ex(const char *fmt, va_list ap)
|
||||
if ((sp = strchr(temp, '\n')) != NULL)
|
||||
*sp = '\0';
|
||||
|
||||
do_pause(2);
|
||||
|
||||
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
|
||||
|
||||
/* Cleanly terminate all of the emulator's components so as
|
||||
to avoid things like threads getting stuck. */
|
||||
do_stop();
|
||||
|
||||
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
|
||||
|
||||
fflush(stdlog);
|
||||
}
|
||||
|
||||
@@ -951,12 +964,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 +986,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;
|
||||
@@ -991,12 +1004,15 @@ 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);
|
||||
gfxcard[1] = 0;
|
||||
// TODO
|
||||
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
|
||||
if (!video_card_available(gfxcard[i])) {
|
||||
char tempc[512] = { 0 };
|
||||
device_get_name(video_card_getdevice(gfxcard[i]), 0, tempc);
|
||||
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[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
atfullspeed = 0;
|
||||
@@ -1076,18 +1092,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 +1148,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 +1190,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 +1251,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 +1309,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
|
||||
|
||||
@@ -21,12 +21,16 @@ 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)
|
||||
endif()
|
||||
|
||||
if(PCL)
|
||||
target_compile_definitions(86Box PRIVATE USE_PCL)
|
||||
endif()
|
||||
|
||||
if(CPPTHREADS)
|
||||
target_sources(86Box PRIVATE thread.cpp)
|
||||
endif()
|
||||
@@ -57,12 +61,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 +234,6 @@ endif()
|
||||
|
||||
if (QT)
|
||||
add_subdirectory(qt)
|
||||
elseif(WIN32)
|
||||
add_subdirectory(win)
|
||||
else()
|
||||
add_compile_definitions(USE_SDL_UI)
|
||||
add_subdirectory(unix)
|
||||
|
||||
@@ -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, <decwiz@yahoo.com>
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
# 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.
|
||||
@@ -1980,6 +1980,9 @@ acpi_reg_write_sis_5595(int size, uint16_t addr, uint8_t val, void *priv)
|
||||
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));
|
||||
|
||||
3129
src/cJSON.c
Normal file
3129
src/cJSON.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,4 +13,13 @@
|
||||
# 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)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(SNDFILE REQUIRED IMPORTED_TARGET sndfile)
|
||||
|
||||
add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_ioctl.c cdrom_mitsumi.c)
|
||||
target_link_libraries(86Box PkgConfig::SNDFILE)
|
||||
if (WIN32)
|
||||
# MSYS2
|
||||
target_link_libraries(86Box -static ${SNDFILE_STATIC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
@@ -1524,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;
|
||||
@@ -1960,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] = '\\';
|
||||
@@ -1970,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2019,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;
|
||||
@@ -2047,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;
|
||||
}
|
||||
@@ -2057,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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -285,7 +294,6 @@ cdrom_image_open(cdrom_t *dev, const char *fn)
|
||||
dev->cd_status = CD_STATUS_DATA_ONLY;
|
||||
else
|
||||
dev->cd_status = CD_STATUS_STOPPED;
|
||||
dev->is_dir = (i == 3);
|
||||
dev->seek_pos = 0;
|
||||
dev->cd_buflen = 0;
|
||||
dev->cdrom_capacity = image_get_capacity(dev);
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* The DOSBox Team, <unknown>
|
||||
* Cacodemon345
|
||||
*
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2017-2020 Fred N. van Kempen.
|
||||
* Copyright 2002-2020 The DOSBox Team.
|
||||
* Copyright 2024 Cacodemon345.
|
||||
*/
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <ctype.h>
|
||||
@@ -40,6 +42,8 @@
|
||||
#include <86box/plat.h>
|
||||
#include <86box/cdrom_image_backend.h>
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4))
|
||||
|
||||
#define MAX_LINE_LENGTH 512
|
||||
@@ -66,16 +70,112 @@ cdrom_image_backend_log(const char *fmt, ...)
|
||||
# define cdrom_image_backend_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct audio_file_t {
|
||||
SNDFILE *file;
|
||||
SF_INFO info;
|
||||
} audio_file_t;
|
||||
|
||||
/* Audio file functions */
|
||||
static int
|
||||
audio_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
|
||||
{
|
||||
track_file_t *tf = (track_file_t *) priv;
|
||||
audio_file_t *audio = (audio_file_t *) tf->priv;
|
||||
uint64_t samples_seek = seek / 4;
|
||||
uint64_t samples_count = count / 4;
|
||||
|
||||
if ((seek & 3) || (count & 3)) {
|
||||
cdrom_image_backend_log("CD Audio file: Reading on non-4-aligned boundaries.\n");
|
||||
}
|
||||
|
||||
sf_count_t res = sf_seek(audio->file, samples_seek, SEEK_SET);
|
||||
|
||||
if (res == -1)
|
||||
return 0;
|
||||
|
||||
return !!sf_readf_short(audio->file, (short *) buffer, samples_count);
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
audio_get_length(void *priv)
|
||||
{
|
||||
track_file_t *tf = (track_file_t *) priv;
|
||||
audio_file_t *audio = (audio_file_t *) tf->priv;
|
||||
|
||||
/* Assume 16-bit audio, 2 channel. */
|
||||
return audio->info.frames * 4ull;
|
||||
}
|
||||
|
||||
static void
|
||||
audio_close(void *priv)
|
||||
{
|
||||
track_file_t *tf = (track_file_t *) priv;
|
||||
audio_file_t *audio = (audio_file_t *) tf->priv;
|
||||
|
||||
memset(tf->fn, 0x00, sizeof(tf->fn));
|
||||
if (audio && audio->file)
|
||||
sf_close(audio->file);
|
||||
free(audio);
|
||||
free(tf);
|
||||
}
|
||||
|
||||
static track_file_t *
|
||||
audio_init(const char *filename, int *error)
|
||||
{
|
||||
track_file_t *tf = (track_file_t *) calloc(sizeof(track_file_t), 1);
|
||||
audio_file_t *audio = (audio_file_t *) calloc(sizeof(audio_file_t), 1);
|
||||
#ifdef _WIN32
|
||||
wchar_t filename_w[4096];
|
||||
#endif
|
||||
|
||||
if (tf == NULL || audio == NULL) {
|
||||
goto cleanup_error;
|
||||
}
|
||||
|
||||
memset(tf->fn, 0x00, sizeof(tf->fn));
|
||||
strncpy(tf->fn, filename, sizeof(tf->fn) - 1);
|
||||
#ifdef _WIN32
|
||||
mbstowcs(filename_w, filename, 4096);
|
||||
audio->file = sf_wchar_open(filename_w, SFM_READ, &audio->info);
|
||||
#else
|
||||
audio->file = sf_open(filename, SFM_READ, &audio->info);
|
||||
#endif
|
||||
|
||||
if (!audio->file) {
|
||||
cdrom_image_backend_log("Audio file open error!");
|
||||
goto cleanup_error;
|
||||
}
|
||||
|
||||
if (audio->info.channels != 2 || audio->info.samplerate != 44100 || !audio->info.seekable) {
|
||||
cdrom_image_backend_log("Audio file not seekable or in non-CD format!");
|
||||
sf_close(audio->file);
|
||||
goto cleanup_error;
|
||||
}
|
||||
|
||||
*error = 0;
|
||||
tf->priv = audio;
|
||||
tf->fp = NULL;
|
||||
tf->close = audio_close;
|
||||
tf->get_length = audio_get_length;
|
||||
tf->read = audio_read;
|
||||
return tf;
|
||||
cleanup_error:
|
||||
free(tf);
|
||||
free(audio);
|
||||
*error = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Binary file functions. */
|
||||
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",
|
||||
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) {
|
||||
@@ -92,22 +192,30 @@ bin_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (UNLIKELY(tf->motorola)) {
|
||||
for (uint64_t i = 0; i < count; i += 2) {
|
||||
uint8_t buffer0 = buffer[i];
|
||||
uint8_t buffer1 = buffer[i + 1];
|
||||
buffer[i] = buffer1;
|
||||
buffer[i + 1] = buffer0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -134,7 +242,7 @@ bin_close(void *priv)
|
||||
static track_file_t *
|
||||
bin_init(const char *filename, int *error)
|
||||
{
|
||||
track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t));
|
||||
track_file_t *tf = (track_file_t *) calloc(1, sizeof(track_file_t));
|
||||
struct stat stats;
|
||||
|
||||
if (tf == NULL) {
|
||||
@@ -248,26 +356,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,13 +388,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;
|
||||
const int pos = trk->start + 150;
|
||||
|
||||
if ((track < 1) || (track > cdi->tracks_num))
|
||||
return 0;
|
||||
|
||||
pos = trk->start + 150;
|
||||
|
||||
FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr);
|
||||
|
||||
*track_num = trk->track_number;
|
||||
@@ -320,9 +420,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 +427,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 +445,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,27 +466,22 @@ 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;
|
||||
int raw_size;
|
||||
int cooked_size;
|
||||
uint64_t offset = 0ULL;
|
||||
int m = 0;
|
||||
int s = 0;
|
||||
int f = 0;
|
||||
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;
|
||||
int m = 0;
|
||||
int s = 0;
|
||||
int f = 0;
|
||||
|
||||
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 +496,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 +505,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 +513,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;
|
||||
int success = 1;
|
||||
|
||||
/* 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 *) calloc(1, 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 +542,7 @@ 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 +557,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 +573,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 +598,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 +614,13 @@ 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 += 24;
|
||||
else
|
||||
seek += 16;
|
||||
} else if (form > 0)
|
||||
seek += 8;
|
||||
|
||||
file->read(file, pvd, seek, COOKED_SECTOR_SIZE);
|
||||
|
||||
@@ -559,68 +643,94 @@ cdi_track_push_back(cd_img_t *cdi, track_t *trk)
|
||||
cdi->tracks_num++;
|
||||
}
|
||||
|
||||
int
|
||||
cdi_get_iso_track(cd_img_t *cdi, track_t *trk, const char *filename)
|
||||
{
|
||||
int error = 0;
|
||||
int ret = 2;
|
||||
memset(trk, 0, sizeof(track_t));
|
||||
|
||||
/* Data track (shouldn't there be a lead in track?). */
|
||||
trk->file = bin_init(filename, &error);
|
||||
if (error) {
|
||||
if ((trk->file != NULL) && (trk->file->close != NULL))
|
||||
trk->file->close(trk->file);
|
||||
ret = 3;
|
||||
trk->file = viso_init(filename, &error);
|
||||
if (error) {
|
||||
if ((trk->file != NULL) && (trk->file->close != NULL))
|
||||
trk->file->close(trk->file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
trk->number = 1;
|
||||
trk->track_number = 1;
|
||||
trk->attr = DATA_TRACK;
|
||||
|
||||
/* Try to detect ISO type. */
|
||||
trk->form = 0;
|
||||
trk->mode2 = 0;
|
||||
|
||||
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)) {
|
||||
trk->sector_size = 2336;
|
||||
trk->mode2 = 1;
|
||||
} else if (cdi_can_read_pvd(trk->file, 2324, 1, 2)) {
|
||||
trk->sector_size = 2324;
|
||||
trk->mode2 = 1;
|
||||
trk->form = 2;
|
||||
trk->noskip = 1;
|
||||
} else if (cdi_can_read_pvd(trk->file, 2328, 1, 2)) {
|
||||
trk->sector_size = 2328;
|
||||
trk->mode2 = 1;
|
||||
trk->form = 2;
|
||||
trk->noskip = 1;
|
||||
} else if (cdi_can_read_pvd(trk->file, 2336, 1, 1)) {
|
||||
trk->sector_size = 2336;
|
||||
trk->mode2 = 1;
|
||||
trk->form = 1;
|
||||
trk->skip = 8;
|
||||
} 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;
|
||||
}
|
||||
|
||||
trk->length = trk->file->get_length(trk->file) / trk->sector_size;
|
||||
cdrom_image_backend_log("ISO: Data track: length = %" PRIu64 ", sector_size = %i\n", trk->length, trk->sector_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
cdi_load_iso(cd_img_t *cdi, const char *filename)
|
||||
{
|
||||
int error;
|
||||
int ret = 2;
|
||||
track_t trk;
|
||||
track_t trk = { 0 };
|
||||
|
||||
cdi->tracks = NULL;
|
||||
cdi->tracks_num = 0;
|
||||
|
||||
memset(&trk, 0, sizeof(track_t));
|
||||
ret = cdi_get_iso_track(cdi, &trk, filename);
|
||||
|
||||
/* Data track (shouldn't there be a lead in track?). */
|
||||
trk.file = bin_init(filename, &error);
|
||||
if (error) {
|
||||
if ((trk.file != NULL) && (trk.file->close != NULL))
|
||||
trk.file->close(trk.file);
|
||||
ret = 3;
|
||||
trk.file = viso_init(filename, &error);
|
||||
if (error) {
|
||||
if ((trk.file != NULL) && (trk.file->close != NULL))
|
||||
trk.file->close(trk.file);
|
||||
return 0;
|
||||
}
|
||||
if (ret >= 1) {
|
||||
cdi_track_push_back(cdi, &trk);
|
||||
|
||||
/* Lead out track. */
|
||||
trk.number = 2;
|
||||
trk.track_number = 0xAA;
|
||||
trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */
|
||||
trk.start = trk.length;
|
||||
trk.length = 0;
|
||||
trk.file = NULL;
|
||||
cdi_track_push_back(cdi, &trk);
|
||||
}
|
||||
trk.number = 1;
|
||||
trk.track_number = 1;
|
||||
trk.attr = DATA_TRACK;
|
||||
|
||||
/* 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)) {
|
||||
trk.sector_size = 2336;
|
||||
trk.mode2 = 1;
|
||||
} else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) {
|
||||
trk.sector_size = 2324;
|
||||
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 {
|
||||
/* We use 2048 mode 1 as the default. */
|
||||
trk.sector_size = COOKED_SECTOR_SIZE;
|
||||
}
|
||||
|
||||
trk.length = trk.file->get_length(trk.file) / trk.sector_size;
|
||||
cdrom_image_backend_log("ISO: Data track: length = %" PRIu64 ", sector_size = %i\n", trk.length, trk.sector_size);
|
||||
cdi_track_push_back(cdi, &trk);
|
||||
|
||||
/* Lead out track. */
|
||||
trk.number = 2;
|
||||
trk.track_number = 0xAA;
|
||||
trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */
|
||||
trk.start = trk.length;
|
||||
trk.length = 0;
|
||||
trk.file = NULL;
|
||||
cdi_track_push_back(cdi, &trk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -711,9 +821,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 +864,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];
|
||||
@@ -779,6 +884,8 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u
|
||||
if (cur->number != 1)
|
||||
return 0;
|
||||
cur->skip = skip * cur->sector_size;
|
||||
if ((cur->sector_size != RAW_SECTOR_SIZE) && (cur->form > 0) && !cur->noskip)
|
||||
cur->skip += 8;
|
||||
cur->start += cur_pregap;
|
||||
*total_pregap = cur_pregap;
|
||||
cdi_track_push_back(cdi, cur);
|
||||
@@ -793,14 +900,16 @@ 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);
|
||||
prev->length = temp / ((uint64_t) prev->sector_size);
|
||||
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++;
|
||||
/* Padding. */
|
||||
|
||||
cur->start += prev->start + prev->length + cur_pregap;
|
||||
cur->skip = skip * cur->sector_size;
|
||||
if ((cur->sector_size != RAW_SECTOR_SIZE) && (cur->form > 0) && !cur->noskip)
|
||||
cur->skip += 8;
|
||||
*shift += prev->start + prev->length;
|
||||
*total_pregap = cur_pregap;
|
||||
}
|
||||
@@ -823,20 +932,18 @@ 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;
|
||||
uint64_t shift = 0ULL;
|
||||
uint64_t prestart = 0ULL;
|
||||
uint64_t cur_pregap = 0ULL;
|
||||
uint64_t total_pregap = 0ULL;
|
||||
uint64_t frame = 0ULL;
|
||||
uint64_t frame = 0ULL;
|
||||
uint64_t index;
|
||||
int iso_file_used = 0;
|
||||
int success;
|
||||
int error;
|
||||
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 +984,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)
|
||||
@@ -887,81 +994,97 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
|
||||
if (!success)
|
||||
break;
|
||||
|
||||
trk.start = 0;
|
||||
trk.skip = 0;
|
||||
cur_pregap = 0;
|
||||
prestart = 0;
|
||||
if (iso_file_used) {
|
||||
/* We don't alter anything of the detected track type with the one specified in the CUE file, except its numbers. */
|
||||
cur_pregap = 0;
|
||||
prestart = 0;
|
||||
|
||||
trk.number = cdi_cue_get_number(&line);
|
||||
trk.track_number = trk.number;
|
||||
success = cdi_cue_get_keyword(&type, &line);
|
||||
if (!success)
|
||||
break;
|
||||
trk.number = cdi_cue_get_number(&line);
|
||||
trk.track_number = trk.number;
|
||||
success = cdi_cue_get_keyword(&type, &line);
|
||||
if (!success)
|
||||
break;
|
||||
can_add_track = 1;
|
||||
|
||||
trk.form = 0;
|
||||
trk.mode2 = 0;
|
||||
iso_file_used = 0;
|
||||
} else {
|
||||
trk.start = 0;
|
||||
trk.skip = 0;
|
||||
cur_pregap = 0;
|
||||
prestart = 0;
|
||||
|
||||
trk.pre = 0;
|
||||
trk.number = cdi_cue_get_number(&line);
|
||||
trk.track_number = trk.number;
|
||||
success = cdi_cue_get_keyword(&type, &line);
|
||||
if (!success)
|
||||
break;
|
||||
|
||||
if (!strcmp(type, "AUDIO")) {
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = AUDIO_TRACK;
|
||||
} else if (!strcmp(type, "MODE1/2048")) {
|
||||
trk.sector_size = COOKED_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
} else if (!strcmp(type, "MODE1/2352")) {
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
} else if (!strcmp(type, "MODE1/2448")) {
|
||||
trk.sector_size = 2448;
|
||||
trk.attr = DATA_TRACK;
|
||||
} else if (!strcmp(type, "MODE2/2048")) {
|
||||
trk.form = 1;
|
||||
trk.sector_size = COOKED_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2324")) {
|
||||
trk.form = 2;
|
||||
trk.sector_size = 2324;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2328")) {
|
||||
trk.form = 2;
|
||||
trk.sector_size = 2328;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2336")) {
|
||||
trk.sector_size = 2336;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2352")) {
|
||||
/* Assume this is XA Mode 2 Form 1. */
|
||||
trk.form = 1;
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2448")) {
|
||||
/* Assume this is XA Mode 2 Form 1. */
|
||||
trk.form = 1;
|
||||
trk.sector_size = 2448;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "CDG/2448")) {
|
||||
trk.sector_size = 2448;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "CDI/2336")) {
|
||||
trk.sector_size = 2336;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "CDI/2352")) {
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else
|
||||
success = 0;
|
||||
trk.form = 0;
|
||||
trk.mode2 = 0;
|
||||
|
||||
can_add_track = 1;
|
||||
trk.pre = 0;
|
||||
|
||||
if (!strcmp(type, "AUDIO")) {
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = AUDIO_TRACK;
|
||||
} else if (!strcmp(type, "MODE1/2048")) {
|
||||
trk.sector_size = COOKED_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
} else if (!strcmp(type, "MODE1/2352")) {
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
} else if (!strcmp(type, "MODE1/2448")) {
|
||||
trk.sector_size = 2448;
|
||||
trk.attr = DATA_TRACK;
|
||||
} else if (!strcmp(type, "MODE2/2048")) {
|
||||
trk.form = 1;
|
||||
trk.sector_size = COOKED_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2324")) {
|
||||
trk.form = 2;
|
||||
trk.sector_size = 2324;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2328")) {
|
||||
trk.form = 2;
|
||||
trk.sector_size = 2328;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2336")) {
|
||||
trk.form = 1;
|
||||
trk.sector_size = 2336;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2352")) {
|
||||
/* Assume this is XA Mode 2 Form 1. */
|
||||
trk.form = 1;
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "MODE2/2448")) {
|
||||
/* Assume this is XA Mode 2 Form 1. */
|
||||
trk.form = 1;
|
||||
trk.sector_size = 2448;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "CDG/2448")) {
|
||||
trk.sector_size = 2448;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "CDI/2336")) {
|
||||
trk.sector_size = 2336;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else if (!strcmp(type, "CDI/2352")) {
|
||||
trk.sector_size = RAW_SECTOR_SIZE;
|
||||
trk.attr = DATA_TRACK;
|
||||
trk.mode2 = 1;
|
||||
} else
|
||||
success = 0;
|
||||
|
||||
can_add_track = 1;
|
||||
}
|
||||
} else if (!strcmp(command, "INDEX")) {
|
||||
index = cdi_cue_get_number(&line);
|
||||
success = cdi_cue_get_frame(&frame, &line);
|
||||
@@ -980,6 +1103,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
|
||||
@@ -1001,14 +1127,40 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
|
||||
trk.file = NULL;
|
||||
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);
|
||||
if (!strcmp(type, "BINARY") || !strcmp(type, "MOTOROLA")) {
|
||||
int fn_len = 0;
|
||||
if (!path_abs(ansi)) {
|
||||
path_append_filename(filename, pathname, ansi);
|
||||
} else {
|
||||
strcpy(filename, ansi);
|
||||
}
|
||||
fn_len = strlen(filename);
|
||||
if ((tolower((int) filename[fn_len - 1]) == 'o'
|
||||
&& tolower((int) filename[fn_len - 2]) == 's'
|
||||
&& tolower((int) filename[fn_len - 3]) == 'i'
|
||||
&& filename[fn_len - 4] == '.')
|
||||
|| plat_dir_check(filename)) {
|
||||
error = !cdi_get_iso_track(cdi, &trk, filename);
|
||||
if (!error) {
|
||||
iso_file_used = 1;
|
||||
}
|
||||
} else
|
||||
trk.file = track_file_init(filename, &error);
|
||||
|
||||
if (trk.file) {
|
||||
trk.file->motorola = !strcmp(type, "MOTOROLA");
|
||||
}
|
||||
} else if (!strcmp(type, "WAVE") || !strcmp(type, "AIFF") || !strcmp(type, "MP3")) {
|
||||
if (!path_abs(ansi)) {
|
||||
path_append_filename(filename, pathname, ansi);
|
||||
} else {
|
||||
strcpy(filename, ansi);
|
||||
}
|
||||
trk.file = audio_init(filename, &error);
|
||||
}
|
||||
if (error) {
|
||||
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
|
||||
cdrom_image_backend_log("CUE: cannot open fille '%s' in cue sheet!\n",
|
||||
cdrom_image_backend_log("CUE: cannot open file '%s' in cue sheet!\n",
|
||||
filename);
|
||||
#endif
|
||||
if (trk.file != NULL) {
|
||||
@@ -1077,7 +1229,7 @@ cdi_has_audio_track(cd_img_t *cdi)
|
||||
if ((cdi == NULL) || (cdi->tracks == NULL))
|
||||
return 0;
|
||||
|
||||
/* Audio track has attribute 0x14. */
|
||||
/* Audio track has attribute 0x10. */
|
||||
for (int i = 0; i < cdi->tracks_num; i++) {
|
||||
if (cdi->tracks[i].attr == AUDIO_TRACK)
|
||||
return 1;
|
||||
|
||||
@@ -46,28 +46,35 @@
|
||||
# define S_ISDIR(m) (((m) &S_IFMT) == S_IFDIR)
|
||||
#endif
|
||||
|
||||
#define VISO_SKIP(p, n) \
|
||||
{ \
|
||||
memset(p, 0x00, n); \
|
||||
p += n; \
|
||||
#ifdef _WIN32
|
||||
# define stat _stat64
|
||||
typedef struct __stat64 stat_t;
|
||||
#else
|
||||
typedef struct stat stat_t;
|
||||
#endif
|
||||
|
||||
#define VISO_SKIP(p, n) \
|
||||
{ \
|
||||
memset((p), 0x00, (n)); \
|
||||
(p) += (n); \
|
||||
}
|
||||
#define VISO_TIME_VALID(t) ((t) > 0)
|
||||
|
||||
/* ISO 9660 defines "both endian" data formats, which
|
||||
are stored as little endian followed by big endian. */
|
||||
#define VISO_LBE_16(p, x) \
|
||||
{ \
|
||||
*((uint16_t *) p) = cpu_to_le16(x); \
|
||||
p += 2; \
|
||||
*((uint16_t *) p) = cpu_to_be16(x); \
|
||||
p += 2; \
|
||||
#define VISO_LBE_16(p, x) \
|
||||
{ \
|
||||
*((uint16_t *) (p)) = cpu_to_le16((x)); \
|
||||
(p) += 2; \
|
||||
*((uint16_t *) (p)) = cpu_to_be16((x)); \
|
||||
(p) += 2; \
|
||||
}
|
||||
#define VISO_LBE_32(p, x) \
|
||||
{ \
|
||||
*((uint32_t *) p) = cpu_to_le32(x); \
|
||||
p += 4; \
|
||||
*((uint32_t *) p) = cpu_to_be32(x); \
|
||||
p += 4; \
|
||||
#define VISO_LBE_32(p, x) \
|
||||
{ \
|
||||
*((uint32_t *) (p)) = cpu_to_le32((x)); \
|
||||
(p) += 4; \
|
||||
*((uint32_t *) (p)) = cpu_to_be32((x)); \
|
||||
(p) += 4; \
|
||||
}
|
||||
|
||||
#define VISO_SECTOR_SIZE COOKED_SECTOR_SIZE
|
||||
@@ -106,7 +113,7 @@ typedef struct _viso_entry_ {
|
||||
};
|
||||
uint16_t pt_idx;
|
||||
|
||||
struct stat stats;
|
||||
stat_t stats;
|
||||
|
||||
struct _viso_entry_ *parent, *next, *next_dir, *first_child;
|
||||
|
||||
@@ -496,10 +503,6 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
|
||||
*p++ = 0; /* extended attribute length */
|
||||
VISO_SKIP(p, 8); /* sector offset */
|
||||
VISO_LBE_32(p, entry->stats.st_size); /* size (filled in later if this is a directory) */
|
||||
#ifdef _WIN32
|
||||
if (entry->stats.st_mtime < 0)
|
||||
pclog("VISO: Warning: Windows returned st_mtime %lld on file [%s]\n", (long long) entry->stats.st_mtime, entry->path);
|
||||
#endif
|
||||
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */
|
||||
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
|
||||
|
||||
@@ -671,9 +674,9 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
|
||||
/* Handle reads in a sector by sector basis. */
|
||||
while (count > 0) {
|
||||
/* Determine the current sector, offset and remainder. */
|
||||
uint32_t sector = seek / viso->sector_size;
|
||||
uint32_t sector_offset = seek % viso->sector_size;
|
||||
uint32_t sector_remain = MIN(count, viso->sector_size - sector_offset);
|
||||
size_t sector = seek / viso->sector_size;
|
||||
size_t sector_offset = seek % viso->sector_size;
|
||||
size_t sector_remain = MIN(count, viso->sector_size - sector_offset);
|
||||
|
||||
/* Handle sector. */
|
||||
if (sector < viso->metadata_sectors) {
|
||||
@@ -830,7 +833,7 @@ viso_init(const char *dirname, int *error)
|
||||
strcpy(dir->path, dirname);
|
||||
if (stat(dirname, &dir->stats) != 0) {
|
||||
/* Use a blank structure if stat failed. */
|
||||
memset(&dir->stats, 0x00, sizeof(struct stat));
|
||||
memset(&dir->stats, 0x00, sizeof(stat_t));
|
||||
}
|
||||
if (!S_ISDIR(dir->stats.st_mode)) /* root is not a directory */
|
||||
goto end;
|
||||
@@ -879,7 +882,7 @@ viso_init(const char *dirname, int *error)
|
||||
/* Stat the current directory or parent directory. */
|
||||
if (stat(children_count ? dir->parent->path : dir->path, &entry->stats) != 0) {
|
||||
/* Use a blank structure if stat failed. */
|
||||
memset(&entry->stats, 0x00, sizeof(struct stat));
|
||||
memset(&entry->stats, 0x00, sizeof(stat_t));
|
||||
}
|
||||
|
||||
/* Set basename. */
|
||||
@@ -909,7 +912,7 @@ viso_init(const char *dirname, int *error)
|
||||
/* Stat this child. */
|
||||
if (stat(entry->path, &entry->stats) != 0) {
|
||||
/* Use a blank structure if stat failed. */
|
||||
memset(&entry->stats, 0x00, sizeof(struct stat));
|
||||
memset(&entry->stats, 0x00, sizeof(stat_t));
|
||||
}
|
||||
|
||||
/* Handle file size and El Torito boot code. */
|
||||
@@ -1432,7 +1435,7 @@ next_entry:
|
||||
/* Allocate entry map for sector->file lookups. */
|
||||
size_t orig_sector_size = viso->sector_size;
|
||||
while (1) {
|
||||
cdrom_image_viso_log("VISO: Allocating entry map for %d %d-byte sectors\n", viso->entry_map_size, viso->sector_size);
|
||||
cdrom_image_viso_log("VISO: Allocating entry map for %zu %zu-byte sectors\n", viso->entry_map_size, viso->sector_size);
|
||||
viso->entry_map = (viso_entry_t **) calloc(viso->entry_map_size, sizeof(viso_entry_t *));
|
||||
if (viso->entry_map) {
|
||||
/* Successfully allocated. */
|
||||
@@ -1444,7 +1447,7 @@ next_entry:
|
||||
|
||||
/* If we don't have enough memory, double the sector size. */
|
||||
viso->sector_size *= 2;
|
||||
if (viso->sector_size == 0) /* give up if sectors become too large */
|
||||
if ((viso->sector_size < VISO_SECTOR_SIZE) || (viso->sector_size > (1 << 30))) /* give up if sectors become too large */
|
||||
goto end;
|
||||
|
||||
/* Go through files, recalculating the entry map size. */
|
||||
@@ -1515,10 +1518,10 @@ next_entry:
|
||||
entry->data_offset = ((uint64_t) viso->all_sectors) * viso->sector_size;
|
||||
|
||||
/* Determine how many sectors this file will take. */
|
||||
uint32_t size = entry->stats.st_size / viso->sector_size;
|
||||
size_t size = entry->stats.st_size / viso->sector_size;
|
||||
if (entry->stats.st_size % viso->sector_size)
|
||||
size++; /* round up to the next sector */
|
||||
cdrom_image_viso_log("[%08X] %s => %" PRIu32 " + %" PRIu32 " sectors\n", entry, entry->path, viso->all_sectors, size);
|
||||
cdrom_image_viso_log("[%08X] %s => %zu + %zu sectors\n", entry, entry->path, viso->all_sectors, size);
|
||||
|
||||
/* Allocate sectors to this file. */
|
||||
viso->all_sectors += size;
|
||||
@@ -1537,13 +1540,13 @@ next_entry:
|
||||
viso_pwrite(data, viso->vol_size_offsets[i], 8, 1, viso->tf.fp);
|
||||
|
||||
/* Metadata processing is finished, read it back to memory. */
|
||||
cdrom_image_viso_log("VISO: Reading back %d %d-byte sectors of metadata\n", viso->metadata_sectors, viso->sector_size);
|
||||
cdrom_image_viso_log("VISO: Reading back %zu %zu-byte sectors of metadata\n", viso->metadata_sectors, viso->sector_size);
|
||||
viso->metadata = (uint8_t *) calloc(viso->metadata_sectors, viso->sector_size);
|
||||
if (!viso->metadata)
|
||||
goto end;
|
||||
fseeko64(viso->tf.fp, 0, SEEK_SET);
|
||||
uint64_t metadata_size = viso->metadata_sectors * viso->sector_size;
|
||||
uint64_t metadata_remain = metadata_size;
|
||||
size_t metadata_size = viso->metadata_sectors * viso->sector_size;
|
||||
size_t metadata_remain = metadata_size;
|
||||
while (metadata_remain > 0)
|
||||
metadata_remain -= fread(viso->metadata + (metadata_size - metadata_remain), 1, MIN(metadata_remain, viso->sector_size), viso->tf.fp);
|
||||
|
||||
|
||||
277
src/cdrom/cdrom_ioctl.c
Normal file
277
src/cdrom/cdrom_ioctl.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* 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, <mariogplayer@gmail.com>,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2023 TheCollector1995.
|
||||
* Copyright 2023 Miran Grca.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#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->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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
#
|
||||
|
||||
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_815ep.c intel_ich2.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
|
||||
opti499.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 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
|
||||
|
||||
199
src/chipset/ali1409.c
Normal file
199
src/chipset/ali1409.c
Normal file
@@ -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, <jose@latinol.com>
|
||||
* Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
*
|
||||
* Copyright 2024 Jose Phillips.
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <86box/vid_cga.h>
|
||||
#include <86box/vid_cga_comp.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
#define RAM_DIAG_L_BASE_MEM_640KB 0x00
|
||||
#define RAM_DIAG_L_BASE_MEM_INV 0x10
|
||||
@@ -746,6 +747,23 @@ compaq_386_init(UNUSED(const device_t *info))
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void
|
||||
compaq_genoa_outw(uint16_t port, uint16_t val, void *priv)
|
||||
{
|
||||
if (port == 0x0c02)
|
||||
cpq_write_regs(0x80c00000, val, priv);
|
||||
}
|
||||
|
||||
static void *
|
||||
compaq_genoa_init(UNUSED(const device_t *info))
|
||||
{
|
||||
void *cpq = device_add(&compaq_386_device);
|
||||
|
||||
io_sethandler(0x0c02, 2, NULL, NULL, NULL, NULL, compaq_genoa_outw, NULL, cpq);
|
||||
|
||||
return ram;
|
||||
}
|
||||
|
||||
const device_t compaq_386_device = {
|
||||
.name = "Compaq 386 Memory Control",
|
||||
.internal_name = "compaq_386",
|
||||
@@ -759,3 +777,17 @@ const device_t compaq_386_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t compaq_genoa_device = {
|
||||
.name = "Compaq Genoa Memory Control",
|
||||
.internal_name = "compaq_genoa",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = compaq_genoa_init,
|
||||
.close = NULL,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <86box/mem.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
#ifdef ENABLE_OPTI283_LOG
|
||||
@@ -215,16 +216,27 @@ opti283_write(uint16_t addr, uint8_t val, void *priv)
|
||||
opti283_t *dev = (opti283_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
dev->index = val;
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
if (dev->index == 0x01)
|
||||
dev->regs[dev->index] = val;
|
||||
break;
|
||||
|
||||
case 0x24:
|
||||
opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);
|
||||
|
||||
switch (dev->index) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
dev->regs[dev->index] = val;
|
||||
dev->regs[dev->index] = (dev->regs[dev->index] & 0x80) | (val & 0x7f);
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
@@ -236,13 +248,9 @@ opti283_write(uint16_t addr, uint8_t val, void *priv)
|
||||
dev->regs[dev->index] = val;
|
||||
opti283_shadow_recalc(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->index = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -250,11 +258,17 @@ opti283_write(uint16_t addr, uint8_t val, void *priv)
|
||||
static uint8_t
|
||||
opti283_read(uint16_t addr, void *priv)
|
||||
{
|
||||
const opti283_t *dev = (opti283_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
opti283_t *dev = (opti283_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (addr == 0x24)
|
||||
if ((addr == 0x23) && (dev->index == 0x01))
|
||||
ret = dev->regs[dev->index];
|
||||
else if (addr == 0x24) {
|
||||
if ((dev->index >= 0x10) && (dev->index <= 0x14))
|
||||
ret = dev->regs[dev->index];
|
||||
|
||||
dev->index = 0xff;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -274,6 +288,7 @@ opti283_init(UNUSED(const device_t *info))
|
||||
memset(dev, 0x00, sizeof(opti283_t));
|
||||
|
||||
io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0023, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0024, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
|
||||
|
||||
dev->regs[0x10] = 0x3f;
|
||||
@@ -296,6 +311,8 @@ opti283_init(UNUSED(const device_t *info))
|
||||
|
||||
opti283_shadow_recalc(dev);
|
||||
|
||||
device_add(&port_92_device);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,34 @@ typedef struct mem_remapping_t {
|
||||
} mem_remapping_t;
|
||||
|
||||
typedef struct opti391_t {
|
||||
uint8_t type;
|
||||
uint8_t reg_base;
|
||||
uint8_t min_reg;
|
||||
uint8_t max_reg;
|
||||
|
||||
uint16_t shadowed;
|
||||
uint16_t old_start;
|
||||
|
||||
uint8_t index;
|
||||
uint8_t regs[256];
|
||||
} opti391_t;
|
||||
|
||||
static void
|
||||
opti391_recalcremap(opti391_t *dev)
|
||||
{
|
||||
if (dev->type < 2) {
|
||||
if ((mem_size > 8192) || (dev->shadowed & 0x0ff0) ||
|
||||
!(dev->regs[0x01] & 0x0f) || !(dev->regs[0x01] & 0x10)) {
|
||||
mem_remap_top_ex(0, dev->old_start);
|
||||
dev->old_start = 1024;
|
||||
} else {
|
||||
mem_remap_top_ex(0, dev->old_start);
|
||||
dev->old_start = (dev->regs[0x01] & 0x0f) * 1024;
|
||||
mem_remap_top_ex(-256, dev->old_start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
opti391_shadow_recalc(opti391_t *dev)
|
||||
{
|
||||
@@ -70,24 +94,25 @@ opti391_shadow_recalc(opti391_t *dev)
|
||||
shadowbios = shadowbios_write = 0;
|
||||
|
||||
/* F0000-FFFFF */
|
||||
sh_enable = !(dev->regs[0x22] & 0x80);
|
||||
sh_enable = (dev->regs[0x02] & 0x80);
|
||||
if (sh_enable)
|
||||
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
else
|
||||
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
|
||||
dev->shadowed |= 0xf000;
|
||||
|
||||
sh_write_internal = (dev->regs[0x26] & 0x40);
|
||||
sh_write_internal = (dev->regs[0x06] & 0x40);
|
||||
/* D0000-EFFFF */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
base = 0xd0000 + (i << 14);
|
||||
if (base >= 0xe0000) {
|
||||
sh_master = (dev->regs[0x22] & 0x40);
|
||||
sh_wp = (dev->regs[0x22] & 0x10);
|
||||
sh_master = (dev->regs[0x02] & 0x20);
|
||||
sh_wp = (dev->regs[0x02] & 0x08);
|
||||
} else {
|
||||
sh_master = (dev->regs[0x22] & 0x20);
|
||||
sh_wp = (dev->regs[0x22] & 0x08);
|
||||
sh_master = (dev->regs[0x02] & 0x40);
|
||||
sh_wp = (dev->regs[0x02] & 0x10);
|
||||
}
|
||||
sh_enable = dev->regs[0x23] & (1 << i);
|
||||
sh_enable = dev->regs[0x03] & (1 << i);
|
||||
|
||||
if (sh_master) {
|
||||
if (sh_enable) {
|
||||
@@ -95,22 +120,29 @@ opti391_shadow_recalc(opti391_t *dev)
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
|
||||
else
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
} else if (sh_write_internal)
|
||||
dev->shadowed |= (1 << (i + 4));
|
||||
} else if (sh_write_internal) {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
else
|
||||
dev->shadowed |= (1 << (i + 4));
|
||||
} else {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
} else if (sh_write_internal)
|
||||
dev->shadowed &= ~(1 << (i + 4));
|
||||
}
|
||||
} else if (sh_write_internal) {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
else
|
||||
dev->shadowed |= (1 << (i + 4));
|
||||
} else {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
dev->shadowed &= ~(1 << (i + 4));
|
||||
}
|
||||
}
|
||||
|
||||
/* C0000-CFFFF */
|
||||
sh_master = !(dev->regs[0x26] & 0x10);
|
||||
sh_wp = (dev->regs[0x26] & 0x20);
|
||||
sh_master = (dev->regs[0x06] & 0x10); /* OPTi 391 datasheet erratum! */
|
||||
sh_wp = (dev->regs[0x06] & 0x20);
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
base = 0xc0000 + (i << 14);
|
||||
sh_enable = dev->regs[0x26] & (1 << i);
|
||||
sh_enable = dev->regs[0x06] & (1 << i);
|
||||
|
||||
if (sh_master) {
|
||||
if (sh_enable) {
|
||||
@@ -118,15 +150,24 @@ opti391_shadow_recalc(opti391_t *dev)
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
|
||||
else
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
} else if (sh_write_internal)
|
||||
dev->shadowed |= (1 << i);
|
||||
} else if (sh_write_internal) {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
else
|
||||
dev->shadowed |= (1 << i);
|
||||
} else {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
} else if (sh_write_internal)
|
||||
dev->shadowed &= ~(1 << i);
|
||||
}
|
||||
} else if (sh_write_internal) {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
else
|
||||
dev->shadowed |= (1 << i);
|
||||
} else {
|
||||
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
dev->shadowed &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
opti391_recalcremap(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -134,7 +175,12 @@ opti391_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
opti391_t *dev = (opti391_t *) priv;
|
||||
|
||||
opti391_log("[W] %04X = %02X\n", addr, val);
|
||||
|
||||
switch (addr) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
dev->index = val;
|
||||
break;
|
||||
@@ -142,35 +188,92 @@ opti391_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x24:
|
||||
opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val);
|
||||
|
||||
switch (dev->index) {
|
||||
case 0x20:
|
||||
dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f);
|
||||
if ((dev->index <= 0x01) && (dev->type < 2)) switch (dev->index) {
|
||||
case 0x00:
|
||||
if (!(dev->regs[0x10] & 0x20) && (val & 0x20)) {
|
||||
softresetx86(); /* Pulse reset! */
|
||||
cpu_set_edx();
|
||||
flushmmucache();
|
||||
}
|
||||
dev->regs[dev->index + 0x10] = val;
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
case 0x24:
|
||||
case 0x25:
|
||||
case 0x27:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2a:
|
||||
case 0x2b:
|
||||
dev->regs[dev->index] = val;
|
||||
case 0x01:
|
||||
dev->regs[dev->index + 0x10] = val;
|
||||
reset_on_hlt = !!(val & 0x02);
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
case 0x23:
|
||||
case 0x26:
|
||||
dev->regs[dev->index] = val;
|
||||
opti391_shadow_recalc(dev);
|
||||
break;
|
||||
|
||||
} else switch (dev->index - dev->reg_base) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case 0x00:
|
||||
if (dev->type == 2) {
|
||||
reset_on_hlt = !!(val & 0x02);
|
||||
if (!(dev->regs[dev->index - dev->reg_base] & 0x01) && (val & 0x01)) {
|
||||
softresetx86(); /* Pulse reset! */
|
||||
cpu_set_edx();
|
||||
flushmmucache();
|
||||
}
|
||||
dev->regs[dev->index - dev->reg_base] =
|
||||
(dev->regs[dev->index - dev->reg_base] & 0xc0) | (val & 0x3f);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
if (dev->type == 2) {
|
||||
cpu_cache_ext_enabled = !!(dev->regs[0x01] & 0x10);
|
||||
cpu_update_waitstates();
|
||||
} else
|
||||
opti391_recalcremap(dev);
|
||||
break;
|
||||
|
||||
case 0x05:
|
||||
if (dev->type == 2)
|
||||
dev->regs[dev->index - dev->reg_base] = val & 0xf8;
|
||||
else
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
case 0x09:
|
||||
case 0x0a:
|
||||
case 0x0b:
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
if (dev->type < 2) {
|
||||
mem_a20_alt = val & 0x08;
|
||||
mem_a20_recalc();
|
||||
}
|
||||
break;
|
||||
case 0x08:
|
||||
if (dev->type == 2)
|
||||
dev->regs[dev->index - dev->reg_base] = val & 0xe3;
|
||||
else {
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x40);
|
||||
cpu_update_waitstates();
|
||||
}
|
||||
break;
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
if (dev->type < 2)
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
opti391_log("Write %02X: %02X\n", dev->index - dev->reg_base, val);
|
||||
dev->regs[dev->index - dev->reg_base] = val;
|
||||
opti391_shadow_recalc(dev);
|
||||
break;
|
||||
}
|
||||
|
||||
dev->index = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,11 +281,19 @@ opti391_write(uint16_t addr, uint8_t val, void *priv)
|
||||
static uint8_t
|
||||
opti391_read(uint16_t addr, void *priv)
|
||||
{
|
||||
const opti391_t *dev = (opti391_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
opti391_t *dev = (opti391_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (addr == 0x24)
|
||||
ret = dev->regs[dev->index];
|
||||
if (addr == 0x24) {
|
||||
if ((dev->index <= 0x01) && (dev->type < 2))
|
||||
ret = dev->regs[dev->index + 0x10];
|
||||
else if ((dev->index >= dev->min_reg) && (dev->index <= dev->max_reg))
|
||||
ret = dev->regs[dev->index - dev->reg_base];
|
||||
|
||||
dev->index = 0xff;
|
||||
}
|
||||
|
||||
opti391_log("[R] %04X = %02X\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -196,32 +307,68 @@ opti391_close(void *priv)
|
||||
}
|
||||
|
||||
static void *
|
||||
opti391_init(UNUSED(const device_t *info))
|
||||
opti391_init(const device_t *info)
|
||||
{
|
||||
opti391_t *dev = (opti391_t *) malloc(sizeof(opti391_t));
|
||||
memset(dev, 0x00, sizeof(opti391_t));
|
||||
opti391_t *dev = (opti391_t *) calloc(1, sizeof(opti391_t));
|
||||
|
||||
io_sethandler(0x0022, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0024, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
|
||||
|
||||
dev->regs[0x21] = 0x84;
|
||||
dev->regs[0x24] = 0x07;
|
||||
dev->regs[0x25] = 0xf0;
|
||||
dev->regs[0x26] = 0x30;
|
||||
dev->regs[0x27] = 0x91;
|
||||
dev->regs[0x28] = 0x80;
|
||||
dev->regs[0x29] = 0x10;
|
||||
dev->regs[0x2a] = 0x80;
|
||||
dev->regs[0x2b] = 0x10;
|
||||
dev->type = info->local;
|
||||
|
||||
if (info->local == 2) {
|
||||
dev->reg_base = 0x20;
|
||||
dev->min_reg = 0x20;
|
||||
dev->max_reg = 0x2b;
|
||||
|
||||
dev->regs[0x02] = 0x84;
|
||||
dev->regs[0x04] = 0x07;
|
||||
dev->regs[0x05] = 0xf0;
|
||||
dev->regs[0x06] = 0x30;
|
||||
dev->regs[0x07] = 0x91;
|
||||
dev->regs[0x08] = 0x80;
|
||||
dev->regs[0x09] = 0x10;
|
||||
dev->regs[0x0a] = 0x80;
|
||||
dev->regs[0x0b] = 0x10;
|
||||
} else {
|
||||
dev->reg_base = 0x0f;
|
||||
dev->min_reg = 0x10;
|
||||
dev->max_reg = 0x1c;
|
||||
|
||||
dev->regs[0x01] = 0x01;
|
||||
dev->regs[0x02] = 0xe0;
|
||||
if (info->local == 1)
|
||||
/* Guess due to no OPTi 48x datasheet. */
|
||||
dev->regs[0x04] = 0x07;
|
||||
else
|
||||
dev->regs[0x04] = 0x77;
|
||||
dev->regs[0x05] = 0x60;
|
||||
dev->regs[0x06] = 0x10;
|
||||
dev->regs[0x07] = 0x50;
|
||||
if (info->local == 1) {
|
||||
/* Guess due to no OPTi 48x datasheet. */
|
||||
dev->regs[0x09] = 0x80; /* Non-Cacheable Block 1 */
|
||||
dev->regs[0x0b] = 0x80; /* Non-Cacheable Block 2 */
|
||||
dev->regs[0x0d] = 0x91; /* Cacheable Area */
|
||||
} else {
|
||||
dev->regs[0x09] = 0xe0; /* Non-Cacheable Block 1 */
|
||||
dev->regs[0x0b] = 0x10; /* Non-Cacheable Block 2 */
|
||||
dev->regs[0x0d] = 0x80; /* Cacheable Area */
|
||||
}
|
||||
dev->regs[0x0a] = 0x10;
|
||||
dev->regs[0x0c] = 0x10;
|
||||
}
|
||||
|
||||
dev->old_start = 1024;
|
||||
|
||||
opti391_shadow_recalc(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t opti391_device = {
|
||||
.name = "OPTi 82C391",
|
||||
.internal_name = "opti391",
|
||||
const device_t opti381_device = {
|
||||
.name = "OPTi 82C381",
|
||||
.internal_name = "opti381",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = opti391_init,
|
||||
@@ -232,3 +379,31 @@ const device_t opti391_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t opti481_device = {
|
||||
.name = "OPTi 82C481",
|
||||
.internal_name = "opti481",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = opti391_init,
|
||||
.close = opti391_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t opti391_device = {
|
||||
.name = "OPTi 82C391",
|
||||
.internal_name = "opti391",
|
||||
.flags = 0,
|
||||
.local = 2,
|
||||
.init = opti391_init,
|
||||
.close = opti391_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include <86box/chipset.h>
|
||||
|
||||
typedef struct opti495_t {
|
||||
uint8_t type;
|
||||
uint8_t max;
|
||||
uint8_t idx;
|
||||
uint8_t regs[256];
|
||||
uint8_t scratch[2];
|
||||
@@ -55,6 +57,22 @@ opti495_log(const char *fmt, ...)
|
||||
# define opti495_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
enum {
|
||||
OPTI493 = 0,
|
||||
OPTI495,
|
||||
OPTI495SLC,
|
||||
OPTI495SX,
|
||||
OPTI495XLC,
|
||||
TMAX
|
||||
};
|
||||
|
||||
/* OPTi 82C493: According to The Last Byte, bit 1 of register 22h, while unused, must still be writable. */
|
||||
static uint8_t masks[TMAX][0x1c] = { { 0x3f, 0xff, 0xff, 0xff, 0xf7, 0xfb, 0x7f, 0x9f, 0xe3, 0xff, 0xe3, 0xff },
|
||||
{ 0x3a, 0x7f, 0xff, 0xff, 0xf0, 0xfb, 0x7f, 0xbf, 0xe3, 0xff, 0x00, 0x00 },
|
||||
{ 0x3a, 0x7f, 0xfc, 0xff, 0xf0, 0xfb, 0xff, 0xbf, 0xe3, 0xff, 0x00, 0x00 },
|
||||
{ 0x3a, 0xff, 0xfd, 0xff, 0xf0, 0xfb, 0x7f, 0xbf, 0xe3, 0xff, 0x00, 0x00 },
|
||||
{ 0x3a, 0xff, 0xfc, 0xff, 0xf0, 0xfb, 0xff, 0xbf, 0xe3, 0xff, 0x00, 0x00 } };
|
||||
|
||||
static void
|
||||
opti495_recalc(opti495_t *dev)
|
||||
{
|
||||
@@ -119,16 +137,25 @@ opti495_write(uint16_t addr, uint8_t val, void *priv)
|
||||
opti495_t *dev = (opti495_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
opti495_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val);
|
||||
dev->idx = val;
|
||||
break;
|
||||
case 0x24:
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
|
||||
dev->regs[dev->idx] = val;
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= dev->max)) {
|
||||
opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
|
||||
|
||||
dev->regs[dev->idx] = val & masks[dev->type][dev->idx - 0x20];
|
||||
if ((dev->type == OPTI493) && (dev->idx == 0x20))
|
||||
val |= 0x40;
|
||||
|
||||
switch (dev->idx) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x21:
|
||||
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
|
||||
cpu_update_waitstates();
|
||||
@@ -139,36 +166,36 @@ opti495_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x26:
|
||||
opti495_recalc(dev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev->idx = 0xff;
|
||||
break;
|
||||
|
||||
case 0xe1:
|
||||
case 0xe2:
|
||||
dev->scratch[~addr & 0x01] = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
opti495_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
const opti495_t *dev = (opti495_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
opti495_t *dev = (opti495_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x22:
|
||||
opti495_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret);
|
||||
break;
|
||||
case 0x24:
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= dev->max)) {
|
||||
ret = dev->regs[dev->idx];
|
||||
opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
|
||||
}
|
||||
|
||||
dev->idx = 0xff;
|
||||
break;
|
||||
case 0xe1:
|
||||
case 0xe2:
|
||||
@@ -202,8 +229,11 @@ opti495_init(const device_t *info)
|
||||
|
||||
dev->scratch[0] = dev->scratch[1] = 0xff;
|
||||
|
||||
if (info->local == 1) {
|
||||
dev->type = info->local;
|
||||
|
||||
if (info->local >= OPTI495) {
|
||||
/* 85C495 */
|
||||
dev->max = 0x29;
|
||||
dev->regs[0x20] = 0x02;
|
||||
dev->regs[0x21] = 0x20;
|
||||
dev->regs[0x22] = 0xe4;
|
||||
@@ -214,6 +244,7 @@ opti495_init(const device_t *info)
|
||||
dev->regs[0x29] = 0x10;
|
||||
} else {
|
||||
/* 85C493 */
|
||||
dev->max = 0x2b;
|
||||
dev->regs[0x20] = 0x40;
|
||||
dev->regs[0x22] = 0x84;
|
||||
dev->regs[0x24] = 0x87;
|
||||
@@ -236,7 +267,7 @@ const device_t opti493_device = {
|
||||
.name = "OPTi 82C493",
|
||||
.internal_name = "opti493",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.local = OPTI493,
|
||||
.init = opti495_init,
|
||||
.close = opti495_close,
|
||||
.reset = NULL,
|
||||
@@ -250,7 +281,7 @@ const device_t opti495_device = {
|
||||
.name = "OPTi 82C495",
|
||||
.internal_name = "opti495",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.local = OPTI495XLC,
|
||||
.init = opti495_init,
|
||||
.close = opti495_close,
|
||||
.reset = NULL,
|
||||
|
||||
@@ -38,6 +38,9 @@ typedef struct opti499_t {
|
||||
uint8_t scratch[2];
|
||||
} opti499_t;
|
||||
|
||||
/* According to The Last Byte, register 2Dh bit 7 must still be writable, even if it is unused. */
|
||||
static uint8_t masks[0x0e] = { 0x3f, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xfb, 0xff, 0x00, 0xff };
|
||||
|
||||
#ifdef ENABLE_OPTI499_LOG
|
||||
int opti499_do_log = ENABLE_OPTI499_LOG;
|
||||
|
||||
@@ -84,7 +87,7 @@ opti499_recalc(opti499_t *dev)
|
||||
shflags = MEM_READ_INTERNAL;
|
||||
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
|
||||
} else {
|
||||
if (dev->regs[0x2d] && (1 << ((i >> 1) + 2)))
|
||||
if (dev->regs[0x2d] & (1 << ((i >> 1) + 2)))
|
||||
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
|
||||
else
|
||||
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
|
||||
@@ -101,13 +104,13 @@ opti499_recalc(opti499_t *dev)
|
||||
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
|
||||
} else {
|
||||
if (dev->regs[0x26] & 0x40) {
|
||||
if (dev->regs[0x2d] && (1 << (i >> 1)))
|
||||
if (dev->regs[0x2d] & (1 << (i >> 1)))
|
||||
shflags = MEM_READ_EXTANY;
|
||||
else
|
||||
shflags = MEM_READ_EXTERNAL;
|
||||
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
|
||||
} else {
|
||||
if (dev->regs[0x2d] && (1 << (i >> 1)))
|
||||
if (dev->regs[0x2d] & (1 << (i >> 1)))
|
||||
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
|
||||
else
|
||||
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
|
||||
@@ -126,19 +129,25 @@ opti499_write(uint16_t addr, uint8_t val, void *priv)
|
||||
opti499_t *dev = (opti499_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val);
|
||||
dev->idx = val;
|
||||
break;
|
||||
case 0x24:
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
|
||||
if (dev->idx == 0x20)
|
||||
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f);
|
||||
else
|
||||
dev->regs[dev->idx] = val;
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d) && (dev->idx != 0x2c)) {
|
||||
opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
|
||||
|
||||
dev->regs[dev->idx] = val & masks[dev->idx - 0x20];
|
||||
if (dev->idx == 0x2a)
|
||||
dev->regs[dev->idx] |= 0x04;
|
||||
|
||||
switch (dev->idx) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
reset_on_hlt = !(val & 0x02);
|
||||
break;
|
||||
@@ -154,20 +163,16 @@ opti499_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x2d:
|
||||
opti499_recalc(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev->idx = 0xff;
|
||||
break;
|
||||
|
||||
case 0xe1:
|
||||
case 0xe2:
|
||||
dev->scratch[~addr & 0x01] = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,25 +183,23 @@ opti499_read(uint16_t addr, void *priv)
|
||||
opti499_t *dev = (opti499_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret);
|
||||
break;
|
||||
case 0x24:
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
|
||||
if (dev->idx == 0x2d)
|
||||
ret = dev->regs[dev->idx] & 0xbf;
|
||||
else
|
||||
ret = dev->regs[dev->idx];
|
||||
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d) && (dev->idx != 0x2c)) {
|
||||
ret = dev->regs[dev->idx];
|
||||
opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
|
||||
}
|
||||
dev->idx = 0xff;
|
||||
break;
|
||||
case 0xe1:
|
||||
case 0xe2:
|
||||
ret = dev->scratch[~addr & 0x01];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -226,8 +229,6 @@ opti499_reset(void *priv)
|
||||
cpu_update_waitstates();
|
||||
|
||||
opti499_recalc(dev);
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -42,6 +42,9 @@ typedef struct opti895_t {
|
||||
smram_t *smram;
|
||||
} opti895_t;
|
||||
|
||||
static uint8_t masks[0x10] = { 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
|
||||
0xe3, 0xff, 0xe3, 0xff, 0x00, 0xff, 0xff, 0xff };
|
||||
|
||||
#ifdef ENABLE_OPTI895_LOG
|
||||
int opti895_do_log = ENABLE_OPTI895_LOG;
|
||||
|
||||
@@ -153,8 +156,12 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
break;
|
||||
case 0x24:
|
||||
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
|
||||
dev->regs[dev->idx] = val;
|
||||
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f) && (dev->idx != 0x2c)) ||
|
||||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
|
||||
if (dev->idx > 0x2f)
|
||||
dev->regs[dev->idx] = val;
|
||||
else
|
||||
dev->regs[dev->idx] = val & masks[dev->idx - 0x20];
|
||||
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
|
||||
|
||||
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
|
||||
@@ -217,7 +224,8 @@ opti895_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
case 0x24:
|
||||
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
|
||||
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
|
||||
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f) && (dev->idx != 0x2c)) ||
|
||||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
|
||||
ret = dev->regs[dev->idx];
|
||||
if (dev->idx == 0xe0)
|
||||
ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -224,6 +224,10 @@ sis_5513_ide_write(int addr, uint8_t val, void *priv)
|
||||
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);
|
||||
|
||||
@@ -86,6 +86,7 @@ typedef struct sis_5513_pci_to_isa_t {
|
||||
port_92_t *port_92;
|
||||
void *pit;
|
||||
nvr_t *nvr;
|
||||
char *fn;
|
||||
ddma_t *ddma;
|
||||
acpi_t *acpi;
|
||||
void *smbus;
|
||||
@@ -1077,7 +1078,6 @@ sis_5513_11_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev)
|
||||
dev->sis->ide_bits_1_3_writable = 0;
|
||||
dev->sis->usb_enabled = 0;
|
||||
|
||||
sis_5513_apc_reset(dev);
|
||||
sis_5513_apc_recalc(dev, 0);
|
||||
}
|
||||
|
||||
@@ -1132,7 +1132,6 @@ sis_5513_b0_pci_to_isa_reset(sis_5513_pci_to_isa_t *dev)
|
||||
|
||||
dev->sis->usb_enabled = 0;
|
||||
|
||||
sis_5513_apc_reset(dev);
|
||||
sis_5513_apc_recalc(dev, 0);
|
||||
|
||||
if (dev->rev == 0x81)
|
||||
@@ -1196,6 +1195,18 @@ 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);
|
||||
}
|
||||
@@ -1205,6 +1216,8 @@ 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;
|
||||
|
||||
@@ -1272,6 +1285,22 @@ sis_5513_pci_to_isa_init(UNUSED(const device_t *info))
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -119,18 +119,18 @@ sis_5571_smram_recalc(sis_5571_host_to_pci_t *dev)
|
||||
{
|
||||
smram_disable_all();
|
||||
|
||||
switch (dev->pci_conf[0x68] >> 6) {
|
||||
switch (dev->pci_conf[0xa3] >> 6) {
|
||||
case 0:
|
||||
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
|
||||
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[0x68] & 0x10, 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[0x68] & 0x10, 1);
|
||||
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[0x68] & 0x10, 1);
|
||||
smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
#include <86box/sis_55xx.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
#define ENABLE_SIS_5581_LOG 1
|
||||
#ifdef ENABLE_SIS_5581_LOG
|
||||
int sis_5581_do_log = ENABLE_SIS_5581_LOG;
|
||||
|
||||
|
||||
@@ -168,7 +168,6 @@ sis_5581_trap_update_devctl(sis_5581_host_to_pci_t *dev, uint8_t trap_id, uint8_
|
||||
uint16_t addr, uint16_t size)
|
||||
{
|
||||
sis_5581_io_trap_t *trap = &dev->io_traps[trap_id];
|
||||
enable = enable;
|
||||
|
||||
/* Set up Device I/O traps dynamically. */
|
||||
if (enable && !trap->trap) {
|
||||
|
||||
@@ -140,7 +140,6 @@ sis_5595_pmu_trap_update_devctl(sis_5595_pmu_t *dev, uint8_t trap_id, uint8_t en
|
||||
uint16_t addr, uint16_t size)
|
||||
{
|
||||
sis_5595_pmu_io_trap_t *trap = &dev->io_traps[trap_id];
|
||||
enable = enable;
|
||||
|
||||
/* Set up Device I/O traps dynamically. */
|
||||
if (enable && !trap->trap) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#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
|
||||
@@ -257,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)) {
|
||||
|
||||
@@ -134,6 +134,36 @@ umc_8886_ide_handler(umc_8886_t *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
umc_8886_bus_recalc(umc_8886_t *dev)
|
||||
{
|
||||
switch (dev->pci_conf_sb[0x00][0xa4] & 0x03) {
|
||||
case 0x00:
|
||||
cpu_set_pci_speed(cpu_busspeed / 2);
|
||||
break;
|
||||
case 0x01:
|
||||
cpu_set_pci_speed(cpu_busspeed);
|
||||
break;
|
||||
case 0x02:
|
||||
cpu_set_pci_speed((cpu_busspeed * 2) / 3);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dev->pci_conf_sb[0x00][0x56] & 0x03) {
|
||||
default:
|
||||
break;
|
||||
case 0x00:
|
||||
cpu_set_isa_pci_div(3);
|
||||
break;
|
||||
case 0x01:
|
||||
cpu_set_isa_pci_div(4);
|
||||
break;
|
||||
case 0x02:
|
||||
cpu_set_isa_pci_div(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
umc_8886_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -191,20 +221,7 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x56:
|
||||
dev->pci_conf_sb[func][addr] = val;
|
||||
|
||||
switch (val & 3) {
|
||||
case 0:
|
||||
cpu_set_isa_pci_div(3);
|
||||
break;
|
||||
case 1:
|
||||
cpu_set_isa_pci_div(4);
|
||||
break;
|
||||
case 2:
|
||||
cpu_set_isa_pci_div(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
umc_8886_bus_recalc(dev);
|
||||
break;
|
||||
|
||||
case 0xa2:
|
||||
@@ -225,7 +242,7 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0xa4:
|
||||
dev->pci_conf_sb[func][addr] = val;
|
||||
cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2));
|
||||
umc_8886_bus_recalc(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -362,8 +379,7 @@ umc_8886_reset(void *priv)
|
||||
for (uint8_t i = 1; i < 5; i++) /* Disable all IRQ interrupts */
|
||||
pci_set_irq_routing(i, PCI_IRQ_DISABLED);
|
||||
|
||||
cpu_set_isa_pci_div(3);
|
||||
cpu_set_pci_speed(cpu_busspeed / 2);
|
||||
umc_8886_bus_recalc(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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; \
|
||||
}
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
182
src/config.c
182
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;
|
||||
@@ -209,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. */
|
||||
@@ -307,9 +314,10 @@ load_machine(void)
|
||||
}
|
||||
}
|
||||
|
||||
cpu_override = ini_section_get_int(cat, "cpu_override", 0);
|
||||
cpu_f = NULL;
|
||||
p = ini_section_get_string(cat, "cpu_family", NULL);
|
||||
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) {
|
||||
/* Migrate CPU family changes. */
|
||||
if ((!strcmp(machines[machine].internal_name, "deskpro386") ||
|
||||
@@ -423,10 +431,17 @@ load_video(void)
|
||||
strcpy(p, "none");
|
||||
}
|
||||
free_p = 1;
|
||||
} else if (!strcmp(p, "c&t_69000")) {
|
||||
p = (char *) malloc((strlen("chips_69000") + 1) * sizeof(char));
|
||||
strcpy(p, "chips_69000");
|
||||
free_p = 1;
|
||||
}
|
||||
gfxcard[0] = video_get_video_from_internal_name(p);
|
||||
if (free_p)
|
||||
if (free_p) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
free_p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (((gfxcard[0] == VID_INTERNAL) && machine_has_flags(machine, MACHINE_VIDEO_8514A)) ||
|
||||
@@ -444,10 +459,13 @@ load_video(void)
|
||||
show_second_monitors = !!ini_section_get_int(cat, "show_second_monitors", 1);
|
||||
video_fullscreen_scale_maximized = !!ini_section_get_int(cat, "video_fullscreen_scale_maximized", 0);
|
||||
|
||||
p = ini_section_get_string(cat, "gfxcard_2", NULL);
|
||||
if (!p)
|
||||
p = "none";
|
||||
gfxcard[1] = video_get_video_from_internal_name(p);
|
||||
// TODO
|
||||
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
|
||||
p = ini_section_get_string(cat, "gfxcard_2", NULL);
|
||||
if (!p)
|
||||
p = "none";
|
||||
gfxcard[i] = video_get_video_from_internal_name(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load "Input Devices" section. */
|
||||
@@ -543,36 +561,24 @@ load_sound(void)
|
||||
char *p;
|
||||
|
||||
p = ini_section_get_string(cat, "sndcard", NULL);
|
||||
/* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */
|
||||
if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci")))
|
||||
p = "es1371";
|
||||
if (p != NULL)
|
||||
sound_card_current[0] = sound_card_get_from_internal_name(p);
|
||||
else
|
||||
sound_card_current[0] = 0;
|
||||
|
||||
p = ini_section_get_string(cat, "sndcard2", NULL);
|
||||
/* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */
|
||||
if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci")))
|
||||
p = "es1371";
|
||||
if (p != NULL)
|
||||
sound_card_current[1] = sound_card_get_from_internal_name(p);
|
||||
else
|
||||
sound_card_current[1] = 0;
|
||||
|
||||
p = ini_section_get_string(cat, "sndcard3", NULL);
|
||||
/* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */
|
||||
if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci")))
|
||||
p = "es1371";
|
||||
if (p != NULL)
|
||||
sound_card_current[2] = sound_card_get_from_internal_name(p);
|
||||
else
|
||||
sound_card_current[2] = 0;
|
||||
|
||||
p = ini_section_get_string(cat, "sndcard4", NULL);
|
||||
/* FIXME: Hack to not break configs with the Sound Blaster 128 PCI set. */
|
||||
if ((p != NULL) && (!strcmp(p, "sbpci128") || !strcmp(p, "sb128pci")))
|
||||
p = "es1371";
|
||||
if (p != NULL)
|
||||
sound_card_current[3] = sound_card_get_from_internal_name(p);
|
||||
else
|
||||
@@ -663,9 +669,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);
|
||||
@@ -710,9 +716,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);
|
||||
@@ -737,7 +743,6 @@ load_ports(void)
|
||||
char *p;
|
||||
char temp[512];
|
||||
int c;
|
||||
int d;
|
||||
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
@@ -760,14 +765,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. */
|
||||
@@ -782,7 +779,7 @@ load_storage_controllers(void)
|
||||
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);
|
||||
@@ -793,10 +790,31 @@ load_storage_controllers(void)
|
||||
}
|
||||
|
||||
p = ini_section_get_string(cat, "fdc", NULL);
|
||||
#if 1
|
||||
if (p != NULL)
|
||||
fdc_type = fdc_card_get_from_internal_name(p);
|
||||
fdc_current[0] = fdc_card_get_from_internal_name(p);
|
||||
else
|
||||
fdc_type = FDC_INTERNAL;
|
||||
fdc_current[0] = FDC_INTERNAL;
|
||||
#else
|
||||
if (p == NULL) {
|
||||
if (machine_has_flags(machine, MACHINE_FDC)) {
|
||||
p = (char *) malloc((strlen("internal") + 1) * sizeof(char));
|
||||
strcpy(p, "internal");
|
||||
} else {
|
||||
p = (char *) malloc((strlen("none") + 1) * sizeof(char));
|
||||
strcpy(p, "none");
|
||||
}
|
||||
free_p = 1;
|
||||
}
|
||||
|
||||
fdc_current[0] = fdc_card_get_from_internal_name(p);
|
||||
|
||||
if (free_p) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
free_p = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
p = ini_section_get_string(cat, "hdc", NULL);
|
||||
if (p == NULL) {
|
||||
@@ -811,15 +829,15 @@ load_storage_controllers(void)
|
||||
}
|
||||
/* Migrate renamed and merged cards. */
|
||||
if (!strcmp(p, "xtide_plus")) {
|
||||
hdc_current = hdc_get_from_internal_name("xtide");
|
||||
hdc_current[0] = 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");
|
||||
hdc_current[0] = 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);
|
||||
hdc_current[0] = hdc_get_from_internal_name(p);
|
||||
|
||||
if (free_p) {
|
||||
free(p);
|
||||
@@ -833,6 +851,7 @@ load_storage_controllers(void)
|
||||
if (free_p) {
|
||||
free(p);
|
||||
p = NULL;
|
||||
free_p = 0;
|
||||
}
|
||||
|
||||
ide_ter_enabled = !!ini_section_get_int(cat, "ide_ter", 0);
|
||||
@@ -876,6 +895,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. */
|
||||
@@ -1174,8 +1195,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);
|
||||
@@ -1262,12 +1282,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);
|
||||
@@ -1288,9 +1302,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);
|
||||
|
||||
@@ -1421,9 +1432,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);
|
||||
|
||||
@@ -1537,9 +1545,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);
|
||||
|
||||
@@ -1568,9 +1573,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);
|
||||
@@ -1616,6 +1622,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");
|
||||
@@ -1623,7 +1631,7 @@ config_load(void)
|
||||
video_fullscreen_first = 1;
|
||||
video_fullscreen_scale = 1;
|
||||
time_sync = TIME_SYNC_ENABLED;
|
||||
hdc_current = hdc_get_from_internal_name("none");
|
||||
hdc_current[0] = hdc_get_from_internal_name("none");
|
||||
|
||||
com_ports[0].enabled = 1;
|
||||
com_ports[1].enabled = 1;
|
||||
@@ -1712,7 +1720,7 @@ save_general(void)
|
||||
char temp[512];
|
||||
char buffer[512] = { 0 };
|
||||
|
||||
const char *va_name = NULL;
|
||||
const char *va_name;
|
||||
|
||||
ini_section_set_int(cat, "vid_resize", vid_resize);
|
||||
if (vid_resize == 0)
|
||||
@@ -1875,6 +1883,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);
|
||||
}
|
||||
|
||||
@@ -1924,6 +1946,10 @@ 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");
|
||||
@@ -1987,10 +2013,13 @@ save_video(void)
|
||||
else
|
||||
ini_section_set_int(cat, "xga", xga_standalone_enabled);
|
||||
|
||||
if (gfxcard[1] == 0)
|
||||
ini_section_delete_var(cat, "gfxcard_2");
|
||||
else
|
||||
ini_section_set_string(cat, "gfxcard_2", video_get_internal_name(gfxcard[1]));
|
||||
// TODO
|
||||
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
|
||||
if (gfxcard[i] == 0)
|
||||
ini_section_delete_var(cat, "gfxcard_2");
|
||||
else
|
||||
ini_section_set_string(cat, "gfxcard_2", video_get_internal_name(gfxcard[i]));
|
||||
}
|
||||
|
||||
if (show_second_monitors == 1)
|
||||
ini_section_delete_var(cat, "show_second_monitors");
|
||||
@@ -2257,7 +2286,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)
|
||||
@@ -2267,14 +2296,14 @@ save_storage_controllers(void)
|
||||
scsi_card_get_internal_name(scsi_card_current[c]));
|
||||
}
|
||||
|
||||
if (fdc_type == FDC_INTERNAL)
|
||||
if (fdc_current[0] == FDC_INTERNAL)
|
||||
ini_section_delete_var(cat, "fdc");
|
||||
else
|
||||
ini_section_set_string(cat, "fdc",
|
||||
fdc_card_get_internal_name(fdc_type));
|
||||
fdc_card_get_internal_name(fdc_current[0]));
|
||||
|
||||
ini_section_set_string(cat, "hdc",
|
||||
hdc_get_internal_name(hdc_current));
|
||||
hdc_get_internal_name(hdc_current[0]));
|
||||
|
||||
if (cdrom_interface_current == 0)
|
||||
ini_section_delete_var(cat, "cdrom_interface");
|
||||
@@ -2341,6 +2370,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. */
|
||||
@@ -2365,6 +2399,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)
|
||||
@@ -2543,10 +2582,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))
|
||||
|
||||
@@ -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>
|
||||
@@ -211,11 +212,11 @@ fetch_ea_16_long(uint32_t rmdat)
|
||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||
|
||||
#define CHECK_READ_CS(size) \
|
||||
if ((cpu_state.pc < cpu_state.seg_cs.limit_low) || \
|
||||
((cpu_state.pc + size - 1) > cpu_state.seg_cs.limit_high)) \
|
||||
x86gpf("Limit check (READ)", 0); \
|
||||
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !(cpu_state.seg_cs.access & 0x80)) \
|
||||
x86np("Read from seg not present", cpu_state.seg_cs.seg & 0xfffc); \
|
||||
else if ((cpu_state.pc < cpu_state.seg_cs.limit_low) || \
|
||||
((cpu_state.pc + size - 1) > cpu_state.seg_cs.limit_high)) \
|
||||
x86gpf("Limit check (READ CS)", 0);
|
||||
|
||||
#include "386_ops.h"
|
||||
|
||||
@@ -260,7 +261,13 @@ exec386_2386(int32_t cycs)
|
||||
|
||||
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
|
||||
ol = opcode_length[fetchdat & 0xff];
|
||||
CHECK_READ_CS(MIN(ol, 4));
|
||||
if ((ol == 3) && opcode_has_modrm[fetchdat & 0xff] && (((fetchdat >> 14) & 0x03) == 0x03))
|
||||
ol = 2;
|
||||
if (cpu_16bitbus) {
|
||||
CHECK_READ_CS(MIN(ol, 2));
|
||||
} else {
|
||||
CHECK_READ_CS(MIN(ol, 4));
|
||||
}
|
||||
ins_fetch_fault = cpu_386_check_instruction_fault();
|
||||
|
||||
/* Breakpoint fault has priority over other faults. */
|
||||
@@ -280,7 +287,10 @@ exec386_2386(int32_t cycs)
|
||||
|
||||
cpu_state.pc++;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -103,6 +106,28 @@ uint32_t backupregs[16];
|
||||
|
||||
x86seg _oldds;
|
||||
|
||||
int opcode_has_modrm[256] = {
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/
|
||||
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/
|
||||
0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/
|
||||
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/
|
||||
|
||||
1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/
|
||||
};
|
||||
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
|
||||
@@ -123,11 +148,11 @@ int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /*
|
||||
/* 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, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x2x */
|
||||
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */
|
||||
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
|
||||
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 */
|
||||
@@ -423,6 +448,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
|
||||
|
||||
@@ -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))))
|
||||
@@ -263,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)));
|
||||
@@ -286,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);
|
||||
@@ -315,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);
|
||||
@@ -354,6 +449,7 @@ get_ram_ptr(uint32_t a)
|
||||
}
|
||||
}
|
||||
|
||||
extern int opcode_has_modrm[256];
|
||||
extern int opcode_length[256];
|
||||
|
||||
#ifdef OPS_286_386
|
||||
@@ -402,6 +498,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)
|
||||
@@ -432,6 +534,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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -3198,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. */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
@@ -38,6 +40,7 @@
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/gdbstub.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
@@ -81,6 +84,12 @@ enum {
|
||||
#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;
|
||||
fpu_state_t fpu_state;
|
||||
@@ -187,6 +196,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;
|
||||
@@ -496,7 +506,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;
|
||||
@@ -1803,7 +1814,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
|
||||
@@ -1971,7 +1983,7 @@ cpu_CPUID(void)
|
||||
} else if (EAX == 1) {
|
||||
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))
|
||||
@@ -1997,7 +2009,7 @@ cpu_CPUID(void)
|
||||
case 1:
|
||||
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))
|
||||
@@ -2008,7 +2020,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))
|
||||
@@ -2046,7 +2058,7 @@ cpu_CPUID(void)
|
||||
} else if (EAX == 1) {
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | 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
|
||||
@@ -2063,7 +2075,7 @@ cpu_CPUID(void)
|
||||
} else if (EAX == 1) {
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE;
|
||||
EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_AMDPGE;
|
||||
} else
|
||||
EAX = EBX = ECX = EDX = 0;
|
||||
break;
|
||||
@@ -2079,7 +2091,7 @@ cpu_CPUID(void)
|
||||
case 1:
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
|
||||
EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
|
||||
break;
|
||||
case 0x80000000:
|
||||
EAX = 0x80000005;
|
||||
@@ -2088,7 +2100,7 @@ cpu_CPUID(void)
|
||||
case 0x80000001:
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_PGE;
|
||||
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 */
|
||||
@@ -2124,7 +2136,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_MMX;
|
||||
break;
|
||||
case 0x80000000:
|
||||
EAX = 0x80000005;
|
||||
@@ -2133,7 +2145,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;
|
||||
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 */
|
||||
@@ -2181,7 +2193,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_MMX;
|
||||
if (cpu_s->cpu_type == CPU_K6_2C)
|
||||
EDX |= CPUID_PGE;
|
||||
break;
|
||||
@@ -2192,7 +2204,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_SEP | 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;
|
||||
@@ -2231,7 +2243,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_PGE | 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;
|
||||
@@ -2240,7 +2252,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_SEP | CPUID_PGE | 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 */
|
||||
@@ -2282,7 +2294,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_PGE | 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;
|
||||
@@ -2291,7 +2303,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_SEP | CPUID_MMX | CPUID_PGE | 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 */
|
||||
@@ -2337,7 +2349,7 @@ cpu_CPUID(void)
|
||||
} 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;
|
||||
@@ -2380,7 +2392,7 @@ cpu_CPUID(void)
|
||||
} 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;
|
||||
@@ -2394,7 +2406,7 @@ cpu_CPUID(void)
|
||||
} 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;
|
||||
@@ -2409,7 +2421,7 @@ cpu_CPUID(void)
|
||||
} 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) {
|
||||
EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
|
||||
Instruction TLB: 4 MB pages, fully associative, 2 entries
|
||||
@@ -2432,7 +2444,7 @@ cpu_CPUID(void)
|
||||
} 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
|
||||
@@ -2455,7 +2467,7 @@ cpu_CPUID(void)
|
||||
} 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
|
||||
@@ -2494,7 +2506,7 @@ cpu_CPUID(void)
|
||||
case 1:
|
||||
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))
|
||||
@@ -2505,7 +2517,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))
|
||||
@@ -3497,7 +3509,7 @@ cpu_WRMSR(void)
|
||||
break;
|
||||
/* Time Stamp Counter */
|
||||
case 0x10:
|
||||
tsc = EAX | ((uint64_t) EDX << 32);
|
||||
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
|
||||
break;
|
||||
/* Performance Monitor - Control and Event Select */
|
||||
case 0x11:
|
||||
@@ -3573,7 +3585,7 @@ cpu_WRMSR(void)
|
||||
break;
|
||||
/* Time Stamp Counter */
|
||||
case 0x10:
|
||||
tsc = EAX | ((uint64_t) EDX << 32);
|
||||
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
|
||||
break;
|
||||
/* PERFCTR0 - Performance Counter Register 0 - aliased to TSC */
|
||||
case 0xc1:
|
||||
@@ -3669,7 +3681,7 @@ cpu_WRMSR(void)
|
||||
break;
|
||||
/* Time Stamp Counter */
|
||||
case 0x00000010:
|
||||
tsc = EAX | ((uint64_t) EDX << 32);
|
||||
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
|
||||
break;
|
||||
/* Array Access Register */
|
||||
case 0x00000082:
|
||||
@@ -3839,7 +3851,7 @@ amd_k_invalid_wrmsr:
|
||||
/* Time Stamp Counter */
|
||||
case 0x00000010:
|
||||
case 0x80000010:
|
||||
tsc = EAX | ((uint64_t) EDX << 32);
|
||||
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
|
||||
break;
|
||||
/* Performance Monitor - Control and Event Select */
|
||||
case 0x00000011:
|
||||
@@ -3924,7 +3936,7 @@ pentium_invalid_wrmsr:
|
||||
msr.tr5 = EAX & 0x008f0f3b;
|
||||
/* Time Stamp Counter */
|
||||
case 0x10:
|
||||
tsc = EAX | ((uint64_t) EDX << 32);
|
||||
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
|
||||
break;
|
||||
/* Performance Monitor - Control and Event Select */
|
||||
case 0x11:
|
||||
@@ -3957,7 +3969,7 @@ pentium_invalid_wrmsr:
|
||||
break;
|
||||
/* Time Stamp Counter */
|
||||
case 0x10:
|
||||
tsc = EAX | ((uint64_t) EDX << 32);
|
||||
timer_set_new_tsc(EAX | ((uint64_t) EDX << 32));
|
||||
break;
|
||||
/* Unknown */
|
||||
case 0x18:
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#ifndef EMU_CPU_H
|
||||
#define EMU_CPU_H
|
||||
|
||||
#include "softfloat/softfloat.h"
|
||||
|
||||
enum {
|
||||
FPU_NONE,
|
||||
FPU_8087,
|
||||
@@ -419,22 +417,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
|
||||
|
||||
@@ -515,7 +497,6 @@ 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 cpu_family_t *cpu_f;
|
||||
@@ -605,8 +586,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;
|
||||
@@ -842,4 +821,9 @@ 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*/
|
||||
|
||||
9795
src/cpu/cpu_table.c
9795
src/cpu/cpu_table.c
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
||||
#ifndef EMU_SF_CONFIG_H
|
||||
#define EMU_SF_CONFIG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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*/
|
||||
@@ -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
|
||||
@@ -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<<negCount) | (a1 != 0);
|
||||
z0 = 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<<negCount) | (a1>>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<<negCount) | (a1>>count) | ((a1<<negCount) != 0);
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if (count == 64) {
|
||||
z1 = a0 | (a1 != 0);
|
||||
}
|
||||
else if (count < 128) {
|
||||
z1 = (a0>>(count & 63)) | (((a0<<negCount) | a1) != 0);
|
||||
}
|
||||
else {
|
||||
z1 = ((a0 | a1) != 0);
|
||||
}
|
||||
z0 = 0;
|
||||
}
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
|
||||
| number of bits given in `count'. Any bits shifted off are lost. The value
|
||||
| of `count' must be less than 64. 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 shortShift128Left(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
|
||||
{
|
||||
*z1Ptr = a1<<count;
|
||||
*z0Ptr = (count == 0) ? a0 : (a0<<count) | (a1>>((-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<<negCount;
|
||||
z1 = (a0<<negCount) | (a1>>count);
|
||||
z0 = a0>>count;
|
||||
}
|
||||
else {
|
||||
if (count == 64) {
|
||||
z2 = a1;
|
||||
z1 = a0;
|
||||
}
|
||||
else {
|
||||
a2 |= a1;
|
||||
if (count < 128) {
|
||||
z2 = a0<<negCount;
|
||||
z1 = 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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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)
|
||||
{
|
||||
Bit16s roundIncrement, roundBits, roundMask;
|
||||
|
||||
int roundingMode = get_float_rounding_mode(status);
|
||||
int roundNearestEven = (roundingMode == float_round_nearest_even);
|
||||
roundIncrement = 8;
|
||||
roundMask = 0xF;
|
||||
|
||||
if (! roundNearestEven) {
|
||||
if (roundingMode == float_round_to_zero) roundIncrement = 0;
|
||||
else {
|
||||
roundIncrement = roundMask;
|
||||
if (zSign) {
|
||||
if (roundingMode == float_round_up) roundIncrement = 0;
|
||||
}
|
||||
else {
|
||||
if (roundingMode == float_round_down) roundIncrement = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
roundBits = zSig & roundMask;
|
||||
if (0x1D <= (Bit16u) zExp) {
|
||||
if ((0x1D < zExp)
|
||||
|| ((zExp == 0x1D) && ((Bit16s) (zSig + roundIncrement) < 0)))
|
||||
{
|
||||
float_raise(status, float_flag_overflow);
|
||||
if (roundBits || float_exception_masked(status, float_flag_overflow)) {
|
||||
float_raise(status, float_flag_inexact);
|
||||
}
|
||||
return packFloat16(zSign, 0x1F, 0) - (roundIncrement == 0);
|
||||
}
|
||||
if (zExp < 0) {
|
||||
int isTiny = (zExp < -1) || (zSig + roundIncrement < 0x8000);
|
||||
zSig = shift16RightJamming(zSig, -zExp);
|
||||
zExp = 0;
|
||||
roundBits = zSig & roundMask;
|
||||
if (isTiny) {
|
||||
if(get_flush_underflow_to_zero(status)) {
|
||||
float_raise(status, float_flag_underflow | float_flag_inexact);
|
||||
return packFloat16(zSign, 0, 0);
|
||||
}
|
||||
// signal the #P according to roundBits calculated AFTER denormalization
|
||||
if (roundBits || !float_exception_masked(status, float_flag_underflow)) {
|
||||
float_raise(status, float_flag_underflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (roundBits) float_raise(status, float_flag_inexact);
|
||||
Bit16u zSigRound = ((zSig + roundIncrement) & ~roundMask) >> 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<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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)
|
||||
{
|
||||
Bit32s roundIncrement, roundBits;
|
||||
const Bit32s roundMask = 0x7F;
|
||||
|
||||
int roundingMode = get_float_rounding_mode(status);
|
||||
int roundNearestEven = (roundingMode == float_round_nearest_even);
|
||||
roundIncrement = 0x40;
|
||||
|
||||
if (! roundNearestEven) {
|
||||
if (roundingMode == float_round_to_zero) roundIncrement = 0;
|
||||
else {
|
||||
roundIncrement = roundMask;
|
||||
if (zSign) {
|
||||
if (roundingMode == float_round_up) roundIncrement = 0;
|
||||
}
|
||||
else {
|
||||
if (roundingMode == float_round_down) roundIncrement = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
roundBits = zSig & roundMask;
|
||||
if (0xFD <= (Bit16u) zExp) {
|
||||
if ((0xFD < zExp)
|
||||
|| ((zExp == 0xFD) && ((Bit32s) (zSig + roundIncrement) < 0)))
|
||||
{
|
||||
float_raise(status, float_flag_overflow);
|
||||
if (roundBits || float_exception_masked(status, float_flag_overflow)) {
|
||||
float_raise(status, float_flag_inexact);
|
||||
if (roundIncrement != 0) set_float_rounding_up(status);
|
||||
}
|
||||
return packFloat32(zSign, 0xFF, 0) - (roundIncrement == 0);
|
||||
}
|
||||
if (zExp < 0) {
|
||||
int isTiny = (zExp < -1) || (zSig + roundIncrement < 0x80000000);
|
||||
if (isTiny) {
|
||||
if (!float_exception_masked(status, float_flag_underflow)) {
|
||||
float_raise(status, float_flag_underflow);
|
||||
zExp += 192; // bias unmasked underflow
|
||||
}
|
||||
}
|
||||
if (zExp < 0) {
|
||||
zSig = shift32RightJamming(zSig, -zExp);
|
||||
zExp = 0;
|
||||
roundBits = zSig & roundMask;
|
||||
if (isTiny) {
|
||||
// masked underflow
|
||||
if(get_flush_underflow_to_zero(status)) {
|
||||
float_raise(status, float_flag_underflow | float_flag_inexact);
|
||||
return packFloat32(zSign, 0, 0);
|
||||
}
|
||||
if (roundBits) float_raise(status, float_flag_underflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Bit32u zSigRound = ((zSig + roundIncrement) & ~roundMask) >> 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<<shiftCount, 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)
|
||||
{
|
||||
int shiftCount = countLeadingZeros64(aSig) - 11;
|
||||
*zSigPtr = aSig<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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)
|
||||
{
|
||||
Bit16s roundIncrement, roundBits;
|
||||
const Bit16s roundMask = 0x3FF;
|
||||
int roundingMode = get_float_rounding_mode(status);
|
||||
int roundNearestEven = (roundingMode == float_round_nearest_even);
|
||||
roundIncrement = 0x200;
|
||||
if (! roundNearestEven) {
|
||||
if (roundingMode == float_round_to_zero) roundIncrement = 0;
|
||||
else {
|
||||
roundIncrement = roundMask;
|
||||
if (zSign) {
|
||||
if (roundingMode == float_round_up) roundIncrement = 0;
|
||||
}
|
||||
else {
|
||||
if (roundingMode == float_round_down) roundIncrement = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
roundBits = (Bit16s)(zSig & roundMask);
|
||||
if (0x7FD <= (Bit16u) zExp) {
|
||||
if ((0x7FD < zExp)
|
||||
|| ((zExp == 0x7FD)
|
||||
&& ((Bit64s) (zSig + roundIncrement) < 0)))
|
||||
{
|
||||
float_raise(status, float_flag_overflow);
|
||||
if (roundBits || float_exception_masked(status, float_flag_overflow)) {
|
||||
float_raise(status, float_flag_inexact);
|
||||
if (roundIncrement != 0) set_float_rounding_up(status);
|
||||
}
|
||||
return packFloat64(zSign, 0x7FF, 0) - (roundIncrement == 0);
|
||||
}
|
||||
if (zExp < 0) {
|
||||
int isTiny = (zExp < -1) || (zSig + roundIncrement < BX_CONST64(0x8000000000000000));
|
||||
if (isTiny) {
|
||||
if (!float_exception_masked(status, float_flag_underflow)) {
|
||||
float_raise(status, float_flag_underflow);
|
||||
zExp += 1536; // bias unmasked underflow
|
||||
}
|
||||
}
|
||||
if (zExp < 0) {
|
||||
zSig = shift64RightJamming(zSig, -zExp);
|
||||
zExp = 0;
|
||||
roundBits = (Bit16s)(zSig & roundMask);
|
||||
if (isTiny) {
|
||||
// masked underflow
|
||||
if(get_flush_underflow_to_zero(status)) {
|
||||
float_raise(status, float_flag_underflow | float_flag_inexact);
|
||||
return packFloat64(zSign, 0, 0);
|
||||
}
|
||||
if (roundBits) float_raise(status, float_flag_underflow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Bit64u zSigRound = (zSig + roundIncrement)>>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<<shiftCount, 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)
|
||||
{
|
||||
int shiftCount = countLeadingZeros64(aSig);
|
||||
*zSigPtr = aSig<<shiftCount;
|
||||
*zExpPtr = 1 - shiftCount;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| 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 SoftFloatRoundAndPackFloatx80(int roundingPrecision,
|
||||
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
|
||||
{
|
||||
Bit64u roundIncrement, roundMask, roundBits;
|
||||
int increment;
|
||||
Bit64u zSigExact; /* support rounding-up response */
|
||||
|
||||
Bit8u roundingMode = get_float_rounding_mode(status);
|
||||
int roundNearestEven = (roundingMode == float_round_nearest_even);
|
||||
if (roundingPrecision == 64) {
|
||||
roundIncrement = BX_CONST64(0x0000000000000400);
|
||||
roundMask = BX_CONST64(0x00000000000007FF);
|
||||
}
|
||||
else if (roundingPrecision == 32) {
|
||||
roundIncrement = BX_CONST64(0x0000008000000000);
|
||||
roundMask = BX_CONST64(0x000000FFFFFFFFFF);
|
||||
}
|
||||
else goto precision80;
|
||||
|
||||
zSig0 |= (zSig1 != 0);
|
||||
if (! roundNearestEven) {
|
||||
if (roundingMode == float_round_to_zero) roundIncrement = 0;
|
||||
else {
|
||||
roundIncrement = roundMask;
|
||||
if (zSign) {
|
||||
if (roundingMode == float_round_up) roundIncrement = 0;
|
||||
}
|
||||
else {
|
||||
if (roundingMode == float_round_down) roundIncrement = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
roundBits = zSig0 & roundMask;
|
||||
if (0x7FFD <= (Bit32u) (zExp - 1)) {
|
||||
if ((0x7FFE < zExp)
|
||||
|| ((zExp == 0x7FFE) && (zSig0 + roundIncrement < zSig0)))
|
||||
{
|
||||
goto overflow;
|
||||
}
|
||||
if (zExp <= 0) {
|
||||
int isTiny = (zExp < 0) || (zSig0 <= zSig0 + roundIncrement);
|
||||
zSig0 = shift64RightJamming(zSig0, 1 - zExp);
|
||||
zSigExact = zSig0;
|
||||
zExp = 0;
|
||||
roundBits = zSig0 & roundMask;
|
||||
if (isTiny) {
|
||||
if (roundBits || (zSig0 && !float_exception_masked(status, float_flag_underflow)))
|
||||
float_raise(status, float_flag_underflow);
|
||||
}
|
||||
zSig0 += roundIncrement;
|
||||
if ((Bit64s) zSig0 < 0) zExp = 1;
|
||||
roundIncrement = roundMask + 1;
|
||||
if (roundNearestEven && (roundBits<<1 == roundIncrement))
|
||||
roundMask |= roundIncrement;
|
||||
zSig0 &= ~roundMask;
|
||||
if (roundBits) {
|
||||
float_raise(status, float_flag_inexact);
|
||||
if (zSig0 > 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
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user