diff --git a/.ci/AppImageBuilder.yml b/.ci/AppImageBuilder.yml index 22db9f1514..64f8f91ed7 100644 --- a/.ci/AppImageBuilder.yml +++ b/.ci/AppImageBuilder.yml @@ -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 diff --git a/.ci/Jenkinsfile b/.ci/Jenkinsfile index a57d3c715e..04b0bc3505 100644 --- a/.ci/Jenkinsfile +++ b/.ci/Jenkinsfile @@ -20,11 +20,12 @@ def repository = ['https://github.com/86Box/86Box.git', scm.userRemoteConfigs[0] def commitBrowser = ['https://github.com/86Box/86Box/commit/%s', null] def branch = ['master', scm.branches[0].name] def buildType = ['beta', 'alpha'] +def tarballFlags = ['', '-s'] def buildBranch = env.JOB_BASE_NAME.contains('-') ? 1 : 0 def osArchs = [ - 'Windows': ['32', '64'], - 'Linux': ['x86', 'x86_64', 'arm32', 'arm64'], + 'Windows': ['64'], + 'Linux': ['x86_64', 'arm64'], 'macOS': ['x86_64+x86_64h+arm64'] ] @@ -238,7 +239,7 @@ pipeline { dir("${env.WORKSPACE_TMP}/output") { /* Run source tarball creation process. */ def packageName = "${env.JOB_BASE_NAME}-Source$buildSuffix" - if (runBuild("-s \"$packageName\"") == 0) { + if (runBuild("-s \"$packageName\" ${tarballFlags[buildBranch]}") == 0) { /* Archive resulting artifacts. */ archiveArtifacts artifacts: "$packageName*" } else { diff --git a/.ci/build.sh b/.ci/build.sh index 1b1e5825e6..c60016d51f 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -208,7 +208,7 @@ cmake_flags_extra= if [ -z "$package_name" -a -z "$tarball_name" ] || [ -n "$package_name" -a -z "$arch" ] then echo '[!] Usage: build.sh -b {package_name} {architecture} [-t] [cmake_flags...]' - echo ' build.sh -s {source_tarball_name}' + echo ' build.sh -s {source_tarball_name} [-t]' echo 'Dep. tree: build.sh -p [archive_tmp/path/to/binary]' exit 100 fi @@ -228,7 +228,10 @@ then [ ! -d "$cwd" ] && mkdir -p "$cwd" # Save current HEAD commit to VERSION. - git log --stat -1 > VERSION || rm -f VERSION + if [ $strip -eq 0 ] + then + git log --stat -1 > VERSION || rm -f VERSION + fi # Archive source. make_tar "$cwd/$tarball_name.tar" @@ -535,6 +538,14 @@ then sudo sed -i -e 's/-no-feature-vulkan/-feature-vulkan/g' "$qt5_portfile" sudo sed -i -e 's/configure.env-append MAKE=/configure.env-append VULKAN_SDK=${prefix} MAKE=/g' "$qt5_portfile" fi + + # Patch wget to remove libproxy support, as it depends on shared-mime-info which + # fails to build for a 10.13 target, which we have to do despite wget only being + # a host dependency. MacPorts issue 69406 strongly implies this will not be fixed. + wget_portfile="$macports/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/net/wget/Portfile" + sudo sed -i -e 's/--enable-libproxy/--disable-libproxy/g' "$wget_portfile" + sudo sed -i -e 's/port:libproxy//g' "$wget_portfile" + while : do # Attempt to install dependencies. @@ -605,7 +616,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) diff --git a/.ci/dependencies_macports.txt b/.ci/dependencies_macports.txt index 5ec71d07cd..b23ac441d5 100644 --- a/.ci/dependencies_macports.txt +++ b/.ci/dependencies_macports.txt @@ -15,3 +15,4 @@ fluidsynth ghostscript libslirp vde2 +libsndfile diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt index 694fe3e289..eacdb8b36f 100644 --- a/.ci/dependencies_msys.txt +++ b/.ci/dependencies_msys.txt @@ -13,3 +13,4 @@ fluidsynth qt5-static qt5-translations vulkan-headers +libsndfile diff --git a/.github/workflows/cmake_linux.yml b/.github/workflows/cmake_linux.yml index 04238ece0d..ed0f055a2f 100644 --- a/.github/workflows/cmake_linux.yml +++ b/.github/workflows/cmake_linux.yml @@ -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: >- diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml index 5a9f31a01f..dc45312f50 100644 --- a/.github/workflows/cmake_macos.yml +++ b/.github/workflows/cmake_macos.yml @@ -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: >- @@ -124,3 +122,102 @@ jobs: 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/** diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 36442684aa..91442eafd2 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -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 @@ -111,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: >- diff --git a/.github/workflows/codeql_linux.yml b/.github/workflows/codeql_linux.yml index 73ccfb2146..fee26a0a66 100644 --- a/.github/workflows/codeql_linux.yml +++ b/.github/workflows/codeql_linux.yml @@ -47,7 +47,7 @@ jobs: # preset: debug # slug: -Debug - name: Dev - preset: experimental + preset: dev_debug slug: -Dev dynarec: - name: ODR diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml index 6d2c3861f3..266a1f051f 100644 --- a/.github/workflows/codeql_macos.yml +++ b/.github/workflows/codeql_macos.yml @@ -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 diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml index 2b468f9960..652a1986aa 100644 --- a/.github/workflows/codeql_windows_msys2.yml +++ b/.github/workflows/codeql_windows_msys2.yml @@ -51,7 +51,7 @@ jobs: # preset: debug # slug: -Debug - name: Dev - preset: experimental + preset: dev_debug slug: -Dev dynarec: - name: ODR diff --git a/CMakeLists.txt b/CMakeLists.txt index fa1d02a151..a70cbd61f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,17 @@ # -# 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. +# 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. +# This file is part of the 86Box distribution. # -# CMake build script. +# CMake build script. # -# Authors: David Hrdlička, +# Authors: David Hrdlička, # -# Copyright 2020-2021 David Hrdlička. +# Copyright 2020-2021 David Hrdlička. +# Copyright 2021-2024 Jasmine Iwanek. # cmake_minimum_required(VERSION 3.16) @@ -35,7 +36,7 @@ if(MUNT_EXTERNAL) endif() project(86Box - VERSION 4.2 + VERSION 4.2.2 DESCRIPTION "Emulator of x86-based systems" HOMEPAGE_URL "https://86box.net" LANGUAGES C CXX) @@ -122,46 +123,55 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON) # Optional features # -# Option Description Def. -# ------ ----------- ---- -option(RELEASE "Release build" OFF) -option(DYNAREC "Dynamic recompiler" ON) -option(OPENAL "OpenAL" ON) -option(RTMIDI "RtMidi" ON) -option(FLUIDSYNTH "FluidSynth" ON) -option(MUNT "MUNT" ON) -option(VNC "VNC renderer" 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(DISCORD "Discord Rich Presence support" ON) -option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF) +# Option Description Def. +# ------ ----------- ---- +option(RELEASE "Release build" OFF) +option(DYNAREC "Dynamic recompiler" ON) +option(OPENAL "OpenAL" ON) +option(RTMIDI "RtMidi" ON) +option(FLUIDSYNTH "FluidSynth" ON) +option(MUNT "MUNT" ON) +option(VNC "VNC renderer" OFF) +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(DISCORD "Discord Rich Presence support" ON) +option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF) if(WIN32) set(QT ON) + option(CPPTHREADS "C++11 threads" OFF) else() option(QT "Qt GUI" ON) + option(CPPTHREADS "C++11 threads" ON) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,wxneeded") endif() # Development branch features # -# Option Description Def. Condition Otherwise -# ------ ----------- ---- --------- --------- -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(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) -cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) -cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) -cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF) -cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF) -cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) +# Option Description Def. Condition Otherwise +# ------ ----------- ---- ------------ --------- +cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF) +cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF) +cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF) +cmake_dependent_option(CYRIX_6X86 "Cyrix 6x86" 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) +cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF) +cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF) +cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF) +cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF) +cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" 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(WACOM "Wacom Input Devices" ON "DEV_BRANCH" OFF) +cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF) # Ditto but for Qt if(QT) diff --git a/CMakePresets.json b/CMakePresets.json index 0dbaf19881..c19a7abc0d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -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" }, diff --git a/README.md b/README.md index b4b4142be5..ce38632e6d 100644 --- a/README.md +++ b/README.md @@ -53,10 +53,14 @@ We operate an IRC channel and a Discord server for discussing 86Box, its develop [![Visit our Discord server](https://discordapp.com/api/guilds/262614059009048590/embed.png)](https://discord.gg/QXK9XTv) Contributions ---------- +------------- We welcome all contributions to the project, as long as the [contribution guidelines](CONTRIBUTING.md) are followed. +Building +--------- +For instructions on how to build 86Box from source, see the [build guide](https://86box.readthedocs.io/en/latest/dev/buildguide.html). + Licensing --------- diff --git a/debian/changelog b/debian/changelog index fe8aa68213..ae80cfa9d4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,5 @@ -86box (4.2) UNRELEASED; urgency=medium +86box (4.2.2) UNRELEASED; urgency=medium * Bump release. - -- Jasmine Iwanek Sat, 23 Mar 2024 17:19:08 +0100 + -- Jasmine Iwanek Sat, 28 Sep 2024 18:31:57 +0200 diff --git a/debian/control b/debian/control index d67f5965ba..a718aee337 100644 --- a/debian/control +++ b/debian/control @@ -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. \ No newline at end of file + fairly recent system designs based on the PCI bus. diff --git a/src/86box.c b/src/86box.c index 61b81bbf3e..5e1f584133 100644 --- a/src/86box.c +++ b/src/86box.c @@ -171,15 +171,15 @@ 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 */ @@ -354,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); @@ -396,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); } @@ -1000,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(STRING_HW_NOT_AVAILABLE_VIDEO2), tempc); - ui_msgbox_header(MBX_INFO, plat_get_string(STRING_HW_NOT_AVAILABLE_TITLE), 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; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5ec2587c2..8f9fb39df2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,16 +12,45 @@ # dob205 # # Copyright 2020-2022 David Hrdlička. -# Copyright 2021 dob205. +# Copyright 2021 dob205. +# Copyright 2024 Jasmine Iwanek. # + if(APPLE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 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 cJSON.c) +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 + cJSON.c +) if(CMAKE_SYSTEM_NAME MATCHES "Linux") add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1) @@ -48,10 +77,6 @@ if(DYNAREC) add_compile_definitions(USE_DYNAREC) endif() -if(DEV_BRANCH) - add_compile_definitions(DEV_BRANCH) -endif() - if(DISCORD) add_compile_definitions(DISCORD) target_sources(86Box PRIVATE discord.c) @@ -65,8 +90,11 @@ 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) + add_library(vnc OBJECT + vnc.c + vnc_keymap.c + ) + target_link_libraries(86Box vnc LibVNCServer::vncserver) if(WIN32) target_link_libraries(86Box ws2_32) endif() @@ -143,8 +171,10 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) include_directories(include) if(NEW_DYNAREC) include_directories(cpu codegen_new) -else() +elseif(DYNAREC) include_directories(cpu codegen) +else() + include_directories(cpu) endif() add_subdirectory(cdrom) @@ -154,7 +184,7 @@ add_subdirectory(usb) add_subdirectory(cpu) if(NEW_DYNAREC) add_subdirectory(codegen_new) -else() +elseif(DYNAREC) add_subdirectory(codegen) endif() diff --git a/src/cdrom/CMakeLists.txt b/src/cdrom/CMakeLists.txt index d3b38095e7..2f0f1cd23e 100644 --- a/src/cdrom/CMakeLists.txt +++ b/src/cdrom/CMakeLists.txt @@ -9,8 +9,31 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_ioctl.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 +) +target_link_libraries(86Box PkgConfig::SNDFILE) + +if(CDROM_MITSUMI) + target_compile_definitions(cdrom PRIVATE USE_CDROM_MITSUMI) + target_sources(cdrom PRIVATE cdrom_mitsumi.c) +endif() + +if (WIN32) + # MSYS2 + target_link_libraries(86Box -static ${SNDFILE_STATIC_LIBRARIES}) +endif() diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 88811c0168..41cc1db982 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -2016,6 +2016,25 @@ cdrom_insert(uint8_t id) dev->insert(dev->priv); } +void +cdrom_exit(uint8_t id) +{ + cdrom_t *dev = &cdrom[id]; + + strcpy(dev->prev_image_path, dev->image_path); + + if (dev->ops) { + if (dev->ops->exit) + dev->ops->exit(dev); + + dev->ops = NULL; + } + + memset(dev->image_path, 0, sizeof(dev->image_path)); + + cdrom_insert(id); +} + /* The mechanics of ejecting a CD-ROM from a drive. */ void cdrom_eject(uint8_t id) @@ -2028,13 +2047,7 @@ cdrom_eject(uint8_t id) return; } - strcpy(dev->prev_image_path, dev->image_path); - - dev->ops->exit(dev); - dev->ops = NULL; - memset(dev->image_path, 0, sizeof(dev->image_path)); - - cdrom_insert(id); + cdrom_exit(id); plat_cdrom_ui_update(id, 0); diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 2203674cdb..113d426c6c 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -294,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); diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 482769799d..7dcde1cdb6 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -14,10 +14,12 @@ * Authors: Miran Grca, * Fred N. van Kempen, * The DOSBox Team, + * 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 @@ -40,6 +42,8 @@ #include <86box/plat.h> #include <86box/cdrom_image_backend.h> +#include + #define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) #define MAX_LINE_LENGTH 512 @@ -66,41 +70,142 @@ 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; - - cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu\n", - tf->fp, seek, count); + track_file_t *tf = NULL; if ((tf = (track_file_t *) priv)->fp == NULL) return 0; + cdrom_image_backend_log("CDROM: binary_read(%08lx, pos=%" PRIu64 " count=%lu)\n", + tf->fp, seek, count); + if (fseeko64(tf->fp, seek, SEEK_SET) == -1) { -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG cdrom_image_backend_log("CDROM: binary_read failed during seek!\n"); -#endif + return 0; } if (fread(buffer, count, 1, tf->fp) != 1) { -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG cdrom_image_backend_log("CDROM: binary_read failed during read!\n"); -#endif + 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) { - track_file_t *tf; - - cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->fp); + track_file_t *tf = NULL; if ((tf = (track_file_t *) priv)->fp == NULL) return 0; @@ -133,7 +238,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) { @@ -279,12 +384,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]; + const int pos = trk->start + 150; if ((track < 1) || (track > cdi->tracks_num)) return 0; - const int pos = trk->start + 150; - FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); *track_num = trk->track_number; @@ -360,20 +464,20 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) { 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; + int raw_size; + int cooked_size; + uint64_t offset; + int m = 0; + int s = 0; + int f = 0; if (track < 0) return 0; - const track_t *trk = &cdi->tracks[track]; - const int 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)); - const uint64_t 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; @@ -420,13 +524,13 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) int cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) { - int success = 1; + int success = 1; /* TODO: This fails to account for Mode 2. Shouldn't we have a function to get sector size? */ - const int sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - const uint32_t buf_len = num * sector_size; - uint8_t *buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); + 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); @@ -434,9 +538,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; } @@ -509,11 +611,12 @@ cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ if (sector_size == RAW_SECTOR_SIZE) { - if (!mode2 || (form == 0)) - seek += 16; - else + if (mode2 && (form > 0)) seek += 24; - } + else + seek += 16; + } else if (form > 0) + seek += 8; file->read(file, pvd, seek, COOKED_SECTOR_SIZE); @@ -537,75 +640,93 @@ cdi_track_push_back(cd_img_t *cdi, track_t *trk) } int -cdi_load_iso(cd_img_t *cdi, const char *filename) +cdi_get_iso_track(cd_img_t *cdi, track_t *trk, const char *filename) { - int error; - int ret = 2; - track_t trk; - - cdi->tracks = NULL; - cdi->tracks_num = 0; - - memset(&trk, 0, sizeof(track_t)); + 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); + 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 ((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); + 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; + 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; - } else if (cdi_can_read_pvd(trk.file, 2328, 1, 2)) { - trk.sector_size = 2328; - trk.mode2 = 1; - trk.form = 2; - } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.mode2 = 1; - } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 1)) { - trk.sector_size = RAW_SECTOR_SIZE; - trk.mode2 = 1; - trk.form = 1; + 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->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); + 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; +} - /* 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); +int +cdi_load_iso(cd_img_t *cdi, const char *filename) +{ + int ret = 2; + track_t trk = { 0 }; + + cdi->tracks = NULL; + cdi->tracks_num = 0; + + ret = cdi_get_iso_track(cdi, &trk, filename); + + 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); + } return ret; } @@ -696,9 +817,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); @@ -759,6 +880,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); @@ -774,13 +897,15 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u cur->start += *total_pregap; } else { const uint64_t temp = prev->file->get_length(prev->file) - (prev->skip); - prev->length = temp / ((uint64_t) prev->sector_size); + 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; } @@ -803,12 +928,13 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) { track_t trk; char pathname[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; @@ -864,81 +990,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; - - trk.number = cdi_cue_get_number(&line); - trk.track_number = trk.number; - success = cdi_cue_get_keyword(&type, &line); - if (!success) - break; + 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.form = 0; - trk.mode2 = 0; - - 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.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.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; + + iso_file_used = 0; + } else { + trk.start = 0; + trk.skip = 0; + 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; - can_add_track = 1; + trk.form = 0; + trk.mode2 = 0; + + 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); @@ -957,8 +1099,8 @@ 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]; + 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); @@ -981,15 +1123,41 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) trk.file = NULL; error = 1; - if (!strcmp(type, "BINARY")) { - 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) { trk.file->close(trk.file); trk.file = NULL; @@ -1004,9 +1172,8 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile) /* Ignored commands. */ success = 1; } else { -#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command); -#endif + success = 0; } @@ -1056,7 +1223,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; diff --git a/src/cdrom/cdrom_image_viso.c b/src/cdrom/cdrom_image_viso.c index 7ed68cd86c..90bd83cf78 100644 --- a/src/cdrom/cdrom_image_viso.c +++ b/src/cdrom/cdrom_image_viso.c @@ -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 @@ viso_init(const char *dirname, int *error) /* 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 @@ viso_init(const char *dirname, int *error) /* 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 @@ viso_init(const char *dirname, int *error) 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 @@ viso_init(const char *dirname, int *error) 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); diff --git a/src/cdrom/cdrom_ioctl.c b/src/cdrom/cdrom_ioctl.c index a204fad0f4..13df2d965c 100644 --- a/src/cdrom/cdrom_ioctl.c +++ b/src/cdrom/cdrom_ioctl.c @@ -254,7 +254,6 @@ cdrom_ioctl_open(cdrom_t *dev, const char *drv) /* All good, reset state. */ dev->cd_status = CD_STATUS_STOPPED; - dev->is_dir = 0; dev->seek_pos = 0; dev->cd_buflen = 0; dev->cdrom_capacity = ioctl_get_capacity(dev); diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 0406ea0b89..6018dd0453 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -9,20 +9,80 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -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 - compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c - intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c - opti602.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c - sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5581.c sis_5591.c sis_5600.c - sis_5511_h2p.c sis_5571_h2p.c sis_5581_h2p.c sis_5591_h2p.c sis_5600_h2p.c - sis_5513_p2i.c sis_5513_ide.c sis_5572_usb.c sis_5595_pmu.c sis_55xx.c via_vt82c49x.c - via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c - umc_8886.c umc_hb4.c umc_8890.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c) +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 + ali1409.c + headland.c + ims8848.c + intel_82335.c + compaq_386.c + contaq_82c59x.c + cs4031.c + intel_420ex.c + intel_4x0.c + intel_i450kx.c + intel_sio.c + intel_piix.c + ../ioapic.c + neat.c + opti283.c + opti291.c + opti391.c + opti495.c + 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 + via_vt82c505.c + gc100.c + stpc.c + umc_8886.c + umc_hb4.c + umc_8890.c + via_apollo.c + via_pipc.c + vl82c480.c + wd76c10.c +) if(OLIVETTI) target_sources(chipset PRIVATE olivetti_eva.c) diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c new file mode 100644 index 0000000000..3e4286f808 --- /dev/null +++ b/src/chipset/ali1409.c @@ -0,0 +1,199 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Implementation of the ALi M1409 chipset. + * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering. + * + * + * + * Authors: Jose Phillips, + * Sarah Walker, + * + * Copyright 2024 Jose Phillips. + * Copyright 2008-2018 Sarah Walker. + */ + + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> + +#include <86box/apm.h> +#include <86box/mem.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/smram.h> +#include <86box/chipset.h> + + + +#ifdef ENABLE_ALI1409_LOG +int ali1409_do_log = ENABLE_ALI1409_LOG; + +static void +ali1409_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1409_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ali1409_log(fmt, ...) +#endif + +typedef struct ali_1409_t { + uint8_t is_g; + uint8_t index; + uint8_t cfg_locked; + uint8_t reg_57h; + uint8_t regs[256]; + uint8_t last_reg; +} ali1409_t; + + +static void +ali1409_write(uint16_t addr, uint8_t val, void *priv) +{ + ali1409_t *dev = (ali1409_t *) priv; + ali1409_log ("INPUT:addr %02x ,Value %02x \n" , addr , val); + + if (addr & 1) { + if (dev->cfg_locked) { + if (dev->last_reg == 0x14 && val == 0x09) + dev->cfg_locked = 0; + + dev->last_reg = val; + return; + } + + if (dev->index == 0xff && val == 0xff) + dev->cfg_locked = 1; + else { + ali1409_log("Write reg %02x %02x %08x\n", dev->index, val, cs); + dev->regs[dev->index] = val; + + switch (dev->index) { + case 0xa: + switch ((val >> 4) & 3) { + case 0: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + break; + case 0xb: + switch ((val >> 4) & 3) { + case 0: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 2: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY| MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + break; + } + } + } else + dev->index = val; +} + + +static uint8_t +ali1409_read(uint16_t addr, void *priv) +{ + ali1409_log ("reading at %02X\n",addr); + const ali1409_t *dev = (ali1409_t *) priv; + uint8_t ret = 0xff; + + if (dev->cfg_locked) + ret = 0xff; + if (addr & 1) { + if ((dev->index >= 0xc0 || dev->index == 0x20) && cpu_iscyrix) + ret = 0xff; + ret = dev->regs[dev->index]; + } else + ret = dev->index; + return ret; +} + + + +static void +ali1409_close(void *priv) +{ + ali1409_t *dev = (ali1409_t *) priv; + + free(dev); +} + +static void * +ali1409_init(const device_t *info) +{ + ali1409_t *dev = (ali1409_t *) malloc(sizeof(ali1409_t)); + memset(dev, 0, sizeof(ali1409_t)); + + dev->cfg_locked = 1; + + /* M1409 Ports: + 22h Index Port + 23h Data Port + */ + + ali1409_log ("Bus speed: %i",cpu_busspeed); + + + io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + io_sethandler(0x037f, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + io_sethandler(0x03f3, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + + return dev; +} + +const device_t ali1409_device = { + .name = "ALi M1409", + .internal_name = "ali1409", + .flags = 0, + .local = 0, + .init = ali1409_init, + .close = ali1409_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/chipset/compaq_386.c b/src/chipset/compaq_386.c index 7d55bc5a5d..8c241e0871 100644 --- a/src/chipset/compaq_386.c +++ b/src/chipset/compaq_386.c @@ -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 +}; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 859cfc5b00..1f379176a3 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -599,9 +599,9 @@ piix_write(int func, int addr, uint8_t val, void *priv) pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf); if (dev->type == 3) { if (val & 0x20) - sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); - else sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY); + else + sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0); } piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled"); } diff --git a/src/chipset/opti283.c b/src/chipset/opti283.c index 1fa59f2f05..63976985be 100644 --- a/src/chipset/opti283.c +++ b/src/chipset/opti283.c @@ -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; } diff --git a/src/chipset/opti391.c b/src/chipset/opti391.c index 03cbb2ea7a..c22c2a04b8 100644 --- a/src/chipset/opti391.c +++ b/src/chipset/opti391.c @@ -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; + } else switch (dev->index - dev->reg_base) { + default: break; - case 0x22: - case 0x23: - case 0x26: - dev->regs[dev->index] = val; - opti391_shadow_recalc(dev); + 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; - default: + 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; } - break; - default: + 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,34 +307,98 @@ 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 opti381_device = { + .name = "OPTi 82C381", + .internal_name = "opti381", + .flags = 0, + .local = 0, + .init = opti391_init, + .close = opti391_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .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 = 0, + .local = 2, .init = opti391_init, .close = opti391_close, .reset = NULL, diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index 13bc2a1245..84ef6a2020 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -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, diff --git a/src/chipset/opti499.c b/src/chipset/opti499.c index f8b8785590..ecadd2224d 100644 --- a/src/chipset/opti499.c +++ b/src/chipset/opti499.c @@ -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 diff --git a/src/chipset/opti5x7.c b/src/chipset/opti5x7.c index 64adacde46..494fdee649 100644 --- a/src/chipset/opti5x7.c +++ b/src/chipset/opti5x7.c @@ -35,7 +35,7 @@ typedef struct opti5x7_t { uint8_t idx; uint8_t is_pci; - uint8_t regs[16]; + uint8_t regs[18]; } opti5x7_t; #ifdef ENABLE_OPTI5X7_LOG @@ -158,7 +158,7 @@ opti5x7_read(uint16_t addr, void *priv) { const opti5x7_t *dev = (opti5x7_t *) priv; - return (addr == 0x24) ? dev->regs[dev->idx] : 0xff; + return ((addr == 0x24) && (dev->idx < sizeof(dev->regs))) ? dev->regs[dev->idx] : 0xff; } static void diff --git a/src/chipset/opti895.c b/src/chipset/opti895.c index 77297ae950..f1878a51bd 100644 --- a/src/chipset/opti895.c +++ b/src/chipset/opti895.c @@ -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; diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index 137ddb5cf2..2286105ce9 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -107,8 +107,8 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev) if (dev->states[8 + i] != state) { mem_set_mem_state_both(base, 0x00004000, state); sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff, - (dev->pci_conf[0x543 & (0x80 >> i)) ? - ((dev->pci_conf[0x54] & 0x40) ? 'I' : 'D') : 'E', + (dev->pci_conf[0x54] & (0x80 >> i)) ? + ((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E', (dev->pci_conf[0x54] & (0x80 >> i)) ? ((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E'); dev->states[8 + i] = state; diff --git a/src/chipset/umc_8886.c b/src/chipset/umc_8886.c index 7a049b1cbe..4242062c6a 100644 --- a/src/chipset/umc_8886.c +++ b/src/chipset/umc_8886.c @@ -126,19 +126,70 @@ umc_8886_ide_handler(umc_8886_t *dev) ide_sec_disable(); if (dev->pci_conf_sb[1][0x04] & 0x01) { - if (dev->pci_conf_sb[1][0x40] & 0x80) + if (dev->pci_conf_sb[1][0x41] & 0x80) ide_pri_enable(); - if (dev->pci_conf_sb[1][0x40] & 0x40) + if (dev->pci_conf_sb[1][0x41] & 0x40) ide_sec_enable(); } } +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_irq_recalc(umc_8886_t *dev) +{ + int irq_routing; + uint8_t *conf = dev->pci_conf_sb[0]; + + irq_routing = (conf[0x46] & 0x01) ? (conf[0x43] >> 4) : PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTA, irq_routing); + irq_routing = (conf[0x46] & 0x02) ? (conf[0x43] & 0x0f) : PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTB, irq_routing); + + irq_routing = (conf[0x46] & 0x04) ? (conf[0x44] >> 4) : PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTC, irq_routing); + irq_routing = (conf[0x46] & 0x08) ? (conf[0x44] & 0x0f) : PCI_IRQ_DISABLED; + pci_set_irq_routing(PCI_INTD, irq_routing); + + pci_set_irq_level(PCI_INTA, (conf[0x47] & 0x01)); + pci_set_irq_level(PCI_INTB, (conf[0x47] & 0x02)); + pci_set_irq_level(PCI_INTC, (conf[0x47] & 0x04)); + pci_set_irq_level(PCI_INTD, (conf[0x47] & 0x08)); +} + static void umc_8886_write(int func, int addr, uint8_t val, void *priv) { umc_8886_t *dev = (umc_8886_t *) priv; - int irq_routing; if (func <= dev->max_func) switch (func) { @@ -153,7 +204,7 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) case 0x50 ... 0x55: case 0x57: case 0x70 ... 0x76: - case 0x80 ... 0x82: + case 0x80 ... 0x83: case 0x90 ... 0x92: case 0xa0 ... 0xa1: case 0xa5 ... 0xa8: @@ -165,46 +216,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) break; case 0x43: - dev->pci_conf_sb[func][addr] = val; - irq_routing = (dev->pci_conf_sb[func][0x46] & 0x01) ? (val >> 8) : - PCI_IRQ_DISABLED; - pci_set_irq_routing(PCI_INTA, irq_routing); - irq_routing = (dev->pci_conf_sb[func][0x46] & 0x02) ? (val & 0x0f) : - PCI_IRQ_DISABLED; - pci_set_irq_routing(PCI_INTB, irq_routing); - break; case 0x44: - dev->pci_conf_sb[func][addr] = val; - irq_routing = (dev->pci_conf_sb[func][0x46] & 0x04) ? (val >> 8) : - PCI_IRQ_DISABLED; - pci_set_irq_routing(PCI_INTC, irq_routing); - irq_routing = (dev->pci_conf_sb[func][0x46] & 0x08) ? (val & 0x0f) : - PCI_IRQ_DISABLED; - pci_set_irq_routing(PCI_INTD, irq_routing); - break; - case 0x46: /* Bits 3-0 = 0 = IRQ disabled, 1 = IRQ enabled. */ case 0x47: /* Bits 3-0 = 0 = IRQ edge-triggered, 1 = IRQ level-triggered. */ /* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */ dev->pci_conf_sb[func][addr] = val; + umc_8886_irq_recalc(dev); break; 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 +247,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: @@ -248,13 +270,13 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv) break; case 0x3c: - case 0x41 ... 0x4b: - case 0x54 ... 0x59: + case 0x40: + case 0x42 ... 0x59: if (dev->ide_id == 0x673a) dev->pci_conf_sb[func][addr] = val; break; - case 0x40: + case 0x41: if (dev->ide_id == 0x673a) { dev->pci_conf_sb[func][addr] = val; umc_8886_ide_handler(dev); @@ -300,25 +322,17 @@ umc_8886_reset(void *priv) dev->pci_conf_sb[0][0x09] = 0x00; dev->pci_conf_sb[0][0x0a] = 0x01; dev->pci_conf_sb[0][0x0b] = 0x06; + dev->pci_conf_sb[0][0x40] = 0x01; - dev->pci_conf_sb[0][0x41] = 0x06; + dev->pci_conf_sb[0][0x41] = 0x04; dev->pci_conf_sb[0][0x42] = 0x08; - dev->pci_conf_sb[0][0x43] = 0x00; - dev->pci_conf_sb[0][0x44] = 0x00; - dev->pci_conf_sb[0][0x45] = 0x04; - dev->pci_conf_sb[0][0x46] = 0x00; - dev->pci_conf_sb[0][0x47] = 0x40; - dev->pci_conf_sb[0][0x50] = 0x01; - dev->pci_conf_sb[0][0x51] = 0x03; - dev->pci_conf_sb[0][0x56] = dev->pci_conf_sb[0][0x57] = 0x00; - dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00; - dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00; - dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x76] = 0x00; - dev->pci_conf_sb[0][0x82] = 0x00; - dev->pci_conf_sb[0][0x90] = dev->pci_conf_sb[0][0x91] = 0x00; - dev->pci_conf_sb[0][0xa0] = dev->pci_conf_sb[0][0xa2] = 0x00; - dev->pci_conf_sb[0][0xa4] = 0x00; - dev->pci_conf_sb[0][0xa8] = 0x20; + dev->pci_conf_sb[0][0x43] = 0x9a; + dev->pci_conf_sb[0][0x44] = 0xbc; + dev->pci_conf_sb[0][0x45] = 0x00; + dev->pci_conf_sb[0][0x46] = 0x10; + dev->pci_conf_sb[0][0x47] = 0x30; + + dev->pci_conf_sb[0][0x51] = 0x02; if (dev->has_ide) { dev->pci_conf_sb[1][0x00] = 0x60; /* UMC */ @@ -341,13 +355,15 @@ umc_8886_reset(void *priv) dev->pci_conf_sb[1][0x21] = 0x10; if (dev->ide_id == 0x673a) { - dev->pci_conf_sb[1][0x40] = 0xc0; - dev->pci_conf_sb[1][0x41] = 0x00; + dev->pci_conf_sb[1][0x40] = 0x00; + dev->pci_conf_sb[1][0x41] = 0xc0; dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00; dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00; dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00; - dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00; - dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x00; + dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x55; + dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x55; + dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x88; + dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0xaa; dev->pci_conf_sb[1][0x54] = dev->pci_conf_sb[1][0x55] = 0x00; dev->pci_conf_sb[1][0x56] = dev->pci_conf_sb[1][0x57] = 0x00; dev->pci_conf_sb[1][0x58] = dev->pci_conf_sb[1][0x59] = 0x00; @@ -362,8 +378,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 diff --git a/src/chipset/umc_hb4.c b/src/chipset/umc_hb4.c index a7ed0b880e..c1f359f261 100644 --- a/src/chipset/umc_hb4.c +++ b/src/chipset/umc_hb4.c @@ -136,6 +136,9 @@ hb4_log(const char *fmt, ...) #endif typedef struct hb4_t { + uint8_t idx; + uint8_t access_data; + uint8_t pci_slot; uint8_t pci_conf[256]; /* PCI Registers */ @@ -176,7 +179,9 @@ hb4_shadow_bios_low(hb4_t *dev) int state; /* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */ - state = shadow_bios[dev->pci_conf[0x55] >> 6]; + state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[dev->pci_conf[0x54] & 0x01] : + MEM_READ_EXTANY; + state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[7]) { mem_set_mem_state_both(0xe0000, 0x10000, state); @@ -194,8 +199,9 @@ hb4_shadow_main(hb4_t *dev) int n = 0; for (uint8_t i = 0; i < 6; i++) { - state = shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] | - shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] : + MEM_READ_EXTANY; + state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[i + 1]) { n++; @@ -212,8 +218,9 @@ hb4_shadow_video(hb4_t *dev) { int state; - state = shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] | - shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; + state = (dev->pci_conf[0x55] & 0x80) ? shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] : + MEM_READ_EXTANY; + state |= shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01]; if (state != dev->mem_state[0]) { mem_set_mem_state_both(0xc0000, 0x8000, state); @@ -302,7 +309,7 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) hb4_shadow(dev); break; - case 0x56 ... 0x5b: + case 0x56 ... 0x5a: case 0x5e ... 0x5f: dev->pci_conf[addr] = val; break; @@ -313,10 +320,14 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv) hb4_smram(dev); break; - case 0x61 ... 0x62: + case 0x61: dev->pci_conf[addr] = val; break; + case 0x62: + dev->pci_conf[addr] = val & 0x03; + break; + default: break; } @@ -354,14 +365,16 @@ hb4_reset(void *priv) dev->pci_conf[0x52] = 0x01; dev->pci_conf[0x53] = 0x00; dev->pci_conf[0x54] = 0x00; - dev->pci_conf[0x55] = 0x00; - dev->pci_conf[0x56] = 0x00; - dev->pci_conf[0x57] = 0x00; - dev->pci_conf[0x58] = 0x00; - dev->pci_conf[0x59] = 0x00; - dev->pci_conf[0x5a] = 0x04; + dev->pci_conf[0x55] = 0x40; + dev->pci_conf[0x56] = 0xff; + dev->pci_conf[0x57] = 0x0f; + dev->pci_conf[0x58] = 0xff; + dev->pci_conf[0x59] = 0x0f; + dev->pci_conf[0x5a] = 0x00; + dev->pci_conf[0x5b] = 0x2c; dev->pci_conf[0x5c] = 0x00; - dev->pci_conf[0x5d] = 0x20; + dev->pci_conf[0x5d] = 0x0f; + dev->pci_conf[0x5e] = 0x00; dev->pci_conf[0x5f] = 0xff; dev->pci_conf[0x60] = 0x00; dev->pci_conf[0x61] = 0x00; @@ -385,6 +398,55 @@ hb4_close(void *priv) free(dev); } +static void +ims8848_write(uint16_t addr, uint8_t val, void *priv) +{ + hb4_t *dev = (hb4_t *) priv; + + switch (addr) { + case 0x22: + dev->idx = val; + break; + case 0x23: + if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0))) + dev->access_data = 1; + break; + case 0x24: + if (dev->access_data) + dev->access_data = 0; + break; + + default: + break; + } +} + +static uint8_t +ims8848_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + hb4_t *dev = (hb4_t *) priv; + + switch (addr) { + case 0x22: + ret = dev->idx; + break; + case 0x23: + ret = (dev->idx >> 4) | (dev->idx << 4); + break; + case 0x24: + if (dev->access_data) { + ret = dev->pci_conf[dev->idx]; + dev->access_data = 0; + } + break; + default: + break; + } + + return ret; +} + static void * hb4_init(UNUSED(const device_t *info)) { @@ -402,6 +464,8 @@ hb4_init(UNUSED(const device_t *info)) dev->smram_base = 0x000a0000; hb4_reset(dev); + io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev); + return dev; } diff --git a/src/chipset/via_apollo.c b/src/chipset/via_apollo.c index 7c1203c3ab..20e2c7f74f 100644 --- a/src/chipset/via_apollo.c +++ b/src/chipset/via_apollo.c @@ -444,7 +444,7 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) apollo_smram_map(dev, 0, 0x000a0000, 0x00020000, 0); break; } - else + else if (dev->id == VIA_595) switch (val & 0x03) { case 0x00: apollo_smram_map(dev, 1, 0x000a0000, 0x00020000, 0); @@ -468,6 +468,12 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) default: break; } + else { + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x00020000, + (dev->pci_conf[0x6d] & 0x10) && (dev->pci_conf[0x63] & 0x01), + dev->pci_conf[0x63] & 0x01); + flushmmucache(); + } break; case 0x65: if (dev->id == VIA_585) @@ -532,6 +538,13 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv) dev->pci_conf[0x6d] = (dev->pci_conf[0x6d] & ~0x7f) | (val & 0x7f); else dev->pci_conf[0x6d] = val; + if (dev->id == VIA_585) { + smram_disable_all(); + smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x00020000, + (dev->pci_conf[0x6d] & 0x10) && (dev->pci_conf[0x63] & 0x01), + dev->pci_conf[0x63] & 0x01); + flushmmucache(); + } break; case 0x6e: if ((dev->id == VIA_595) || (dev->id == VIA_694)) diff --git a/src/codegen/CMakeLists.txt b/src/codegen/CMakeLists.txt index 3cb9de6cab..3d000c98d6 100644 --- a/src/codegen/CMakeLists.txt +++ b/src/codegen/CMakeLists.txt @@ -9,19 +9,28 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # if(DYNAREC) - add_library(dynarec OBJECT codegen.c codegen_ops.c) + add_library(dynarec OBJECT + codegen.c + codegen_ops.c + ) if(ARCH STREQUAL "i386") - target_sources(dynarec PRIVATE codegen_x86.c - codegen_accumulate_x86.c) + target_sources(dynarec PRIVATE + codegen_x86.c + codegen_accumulate_x86.c + ) elseif(ARCH STREQUAL "x86_64") - target_sources(dynarec PRIVATE codegen_x86-64.c - codegen_accumulate_x86-64.c) + target_sources(dynarec PRIVATE + codegen_x86-64.c + codegen_accumulate_x86-64.c + ) else() message(SEND_ERROR "Dynarec is incompatible with target platform ${ARCH}") diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h index 6d30211a69..d020fc57fd 100644 --- a/src/codegen/codegen.h +++ b/src/codegen/codegen.h @@ -311,6 +311,7 @@ extern codegen_timing_t codegen_timing_686; extern codegen_timing_t codegen_timing_486; extern codegen_timing_t codegen_timing_winchip; extern codegen_timing_t codegen_timing_winchip2; +extern codegen_timing_t codegen_timing_k5; extern codegen_timing_t codegen_timing_k6; extern codegen_timing_t codegen_timing_p6; diff --git a/src/codegen/codegen_ops.c b/src/codegen/codegen_ops.c index a81eef67e1..c8e258e788 100644 --- a/src/codegen/codegen_ops.c +++ b/src/codegen/codegen_ops.c @@ -12,6 +12,7 @@ #include "x86_flags.h" #include "x86seg_common.h" #include "x86seg.h" +#include "x87_sf.h" #include "x87.h" #include "386_common.h" #include "cpu.h" diff --git a/src/codegen/codegen_ops_x86-64.h b/src/codegen/codegen_ops_x86-64.h index bc6293c0bf..08b9ee5f24 100644 --- a/src/codegen/codegen_ops_x86-64.h +++ b/src/codegen/codegen_ops_x86-64.h @@ -4434,7 +4434,7 @@ FP_COMPARE_REG(int dst, int src) addbyte((uint8_t) cpu_state_offset(npxs) + 1); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); if (src) { addbyte(0xf3); /*MOVQ XMM0, ST[RBX*8]*/ @@ -4467,7 +4467,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0x9f); /*LAHF*/ addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ @@ -4493,7 +4493,7 @@ FP_COMPARE_MEM(void) addbyte((uint8_t) cpu_state_offset(ST)); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0x66); /*COMISD XMM0, XMM1*/ addbyte(0x0f); addbyte(0x2f); @@ -4501,7 +4501,7 @@ FP_COMPARE_MEM(void) addbyte(0x9f); /*LAHF*/ addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ diff --git a/src/codegen/codegen_ops_x86.h b/src/codegen/codegen_ops_x86.h index 410ce8e17a..c48324c2a9 100644 --- a/src/codegen/codegen_ops_x86.h +++ b/src/codegen/codegen_ops_x86.h @@ -2911,7 +2911,7 @@ FP_COMPARE_S(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xd8); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -2919,7 +2919,7 @@ FP_COMPARE_S(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -2943,7 +2943,7 @@ FP_COMPARE_S(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xd8); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -2951,7 +2951,7 @@ FP_COMPARE_S(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -2980,7 +2980,7 @@ FP_COMPARE_D(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xdc); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -2988,7 +2988,7 @@ FP_COMPARE_D(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3016,7 +3016,7 @@ FP_COMPARE_D(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xdc); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3024,7 +3024,7 @@ FP_COMPARE_D(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3050,7 +3050,7 @@ FP_COMPARE_IW(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xde); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3058,7 +3058,7 @@ FP_COMPARE_IW(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3082,7 +3082,7 @@ FP_COMPARE_IW(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xde); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3090,7 +3090,7 @@ FP_COMPARE_IW(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3115,7 +3115,7 @@ FP_COMPARE_IL(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xda); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3123,7 +3123,7 @@ FP_COMPARE_IL(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3147,7 +3147,7 @@ FP_COMPARE_IL(void) addbyte(0xe2); addbyte(0x80); /*AND BL, ~(C0|C2|C3)*/ addbyte(0xe3); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xda); /*FCOMP [ESP]*/ addbyte(0x04 | 0x18); addbyte(0x24); @@ -3155,7 +3155,7 @@ FP_COMPARE_IL(void) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR BL, AH*/ addbyte(0xe3); addbyte(0x88); /*MOV [npxs+1], BL*/ @@ -3250,7 +3250,7 @@ FP_COMPARE_REG(int dst, int src) addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + dst) & 7])); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); addbyte(0xdc); /*FCOMP ST[src][EBP]*/ addbyte(0x5d); addbyte((uint8_t) cpu_state_offset(ST[(cpu_state.TOP + src) & 7])); @@ -3258,7 +3258,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ @@ -3286,7 +3286,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0xe2); addbyte(0x80); /*AND CL, ~(C0|C2|C3)*/ addbyte(0xe1); - addbyte((~(C0 | C2 | C3)) >> 8); + addbyte((~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)) >> 8); if (src) { addbyte(0xdd); /*FLD ST[EBX*8]*/ @@ -3312,7 +3312,7 @@ FP_COMPARE_REG(int dst, int src) addbyte(0xe0); addbyte(0x80); /*AND AH, (C0|C2|C3)*/ addbyte(0xe4); - addbyte((C0 | C2 | C3) >> 8); + addbyte((FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3) >> 8); addbyte(0x08); /*OR CL, AH*/ addbyte(0xe1); addbyte(0x88); /*MOV [npxs+1], CL*/ diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index 421f200262..9588721623 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -13,6 +13,7 @@ # include "x86_ops.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" # include <86box/mem.h> # include <86box/plat_unused.h> diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index 456f93ae9b..74c209001b 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -51,6 +51,7 @@ # include "x86_ops.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" /*ex*/ # include <86box/nmi.h> diff --git a/src/codegen_new/CMakeLists.txt b/src/codegen_new/CMakeLists.txt index 038f1edd16..cee7d5cb9c 100644 --- a/src/codegen_new/CMakeLists.txt +++ b/src/codegen_new/CMakeLists.txt @@ -9,39 +9,71 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # if(DYNAREC) - add_library(dynarec OBJECT codegen.c codegen_accumulate.c - codegen_allocator.c codegen_block.c codegen_ir.c codegen_ops.c - codegen_ops_3dnow.c codegen_ops_branch.c codegen_ops_arith.c - codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c - codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c - codegen_ops_helpers.c codegen_ops_jump.c codegen_ops_logic.c - codegen_ops_misc.c codegen_ops_mmx_arith.c codegen_ops_mmx_cmp.c - codegen_ops_mmx_loadstore.c codegen_ops_mmx_logic.c - codegen_ops_mmx_pack.c codegen_ops_mmx_shift.c codegen_ops_mov.c - codegen_ops_shift.c codegen_ops_stack.c codegen_reg.c) + add_library(dynarec OBJECT + codegen.c + codegen_accumulate.c + codegen_allocator.c + codegen_block.c + codegen_ir.c + codegen_ops.c + codegen_ops_3dnow.c + codegen_ops_branch.c + codegen_ops_arith.c + codegen_ops_fpu_arith.c + codegen_ops_fpu_constant.c + codegen_ops_fpu_loadstore.c + codegen_ops_fpu_misc.c + codegen_ops_helpers.c + codegen_ops_jump.c + codegen_ops_logic.c + codegen_ops_misc.c + codegen_ops_mmx_arith.c + codegen_ops_mmx_cmp.c + codegen_ops_mmx_loadstore.c + codegen_ops_mmx_logic.c + codegen_ops_mmx_pack.c + codegen_ops_mmx_shift.c + codegen_ops_mov.c + codegen_ops_shift.c + codegen_ops_stack.c + codegen_reg.c + ) if(ARCH STREQUAL "i386") - target_sources(dynarec PRIVATE codegen_backend_x86.c - codegen_backend_x86_ops.c codegen_backend_x86_ops_fpu.c + target_sources(dynarec PRIVATE + codegen_backend_x86.c + codegen_backend_x86_ops.c + codegen_backend_x86_ops_fpu.c codegen_backend_x86_ops_sse.c - codegen_backend_x86_uops.c) + codegen_backend_x86_uops.c + ) elseif(ARCH STREQUAL "x86_64") - target_sources(dynarec PRIVATE codegen_backend_x86-64.c + target_sources(dynarec PRIVATE + codegen_backend_x86-64.c codegen_backend_x86-64_ops.c codegen_backend_x86-64_ops_sse.c - codegen_backend_x86-64_uops.c) + codegen_backend_x86-64_uops.c + ) elseif(ARCH STREQUAL "arm64") - target_sources(dynarec PRIVATE codegen_backend_arm64.c - codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c - codegen_backend_arm64_imm.c) + target_sources(dynarec PRIVATE + codegen_backend_arm64.c + codegen_backend_arm64_ops.c + codegen_backend_arm64_uops.c + codegen_backend_arm64_imm.c + ) elseif(ARCH STREQUAL "arm") - target_sources(dynarec PRIVATE codegen_backend_arm.c - codegen_backend_arm_ops.c codegen_backend_arm_uops.c) + target_sources(dynarec PRIVATE + codegen_backend_arm.c + codegen_backend_arm_ops.c + codegen_backend_arm_uops.c + ) else() message(SEND_ERROR "Dynarec is incompatible with target platform ${ARCH}") diff --git a/src/codegen_new/codegen.h b/src/codegen_new/codegen.h index deeeb899c8..eecfa249bf 100644 --- a/src/codegen_new/codegen.h +++ b/src/codegen_new/codegen.h @@ -341,6 +341,7 @@ extern codegen_timing_t codegen_timing_686; extern codegen_timing_t codegen_timing_486; extern codegen_timing_t codegen_timing_winchip; extern codegen_timing_t codegen_timing_winchip2; +extern codegen_timing_t codegen_timing_k5; extern codegen_timing_t codegen_timing_k6; extern codegen_timing_t codegen_timing_p6; diff --git a/src/codegen_new/codegen_backend_arm.c b/src/codegen_new/codegen_backend_arm.c index b1e904096c..9c480dccf6 100644 --- a/src/codegen_new/codegen_backend_arm.c +++ b/src/codegen_new/codegen_backend_arm.c @@ -15,6 +15,7 @@ # include "x86.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" # if defined(__linux__) || defined(__APPLE__) diff --git a/src/codegen_new/codegen_backend_arm64.c b/src/codegen_new/codegen_backend_arm64.c index 1eb94a9090..5c2233b635 100644 --- a/src/codegen_new/codegen_backend_arm64.c +++ b/src/codegen_new/codegen_backend_arm64.c @@ -15,6 +15,7 @@ # include "x86.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" # if defined(__linux__) || defined(__APPLE__) diff --git a/src/codegen_new/codegen_backend_arm64_uops.c b/src/codegen_new/codegen_backend_arm64_uops.c index 7514e1f0c3..deaf53c200 100644 --- a/src/codegen_new/codegen_backend_arm64_uops.c +++ b/src/codegen_new/codegen_backend_arm64_uops.c @@ -9,6 +9,7 @@ # include "x86.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" # include "386_common.h" # include "codegen.h" @@ -648,10 +649,10 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_arm64_FSUB_D(block, REG_V_TEMP, REG_V_TEMP, REG_V_TEMP); host_arm64_MOVZ_IMM(block, dest_reg, 0); host_arm64_FCMP_D(block, src_reg_a, REG_V_TEMP); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, FPU_SW_C0); host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); } else @@ -690,10 +691,10 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) if (REG_IS_W(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b)) { host_arm64_MOVZ_IMM(block, dest_reg, 0); host_arm64_FCMP_D(block, src_reg_a, src_reg_b); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C3); - host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, C0); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C3); + host_arm64_ORR_IMM(block, REG_TEMP2, dest_reg, FPU_SW_C0); host_arm64_CSEL_EQ(block, dest_reg, REG_TEMP, dest_reg); - host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, C0 | C2 | C3); + host_arm64_ORR_IMM(block, REG_TEMP, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); host_arm64_CSEL_CC(block, dest_reg, REG_TEMP2, dest_reg); host_arm64_CSEL_VS(block, dest_reg, REG_TEMP, dest_reg); } else diff --git a/src/codegen_new/codegen_backend_arm_uops.c b/src/codegen_new/codegen_backend_arm_uops.c index 338d3dd546..d8c2238845 100644 --- a/src/codegen_new/codegen_backend_arm_uops.c +++ b/src/codegen_new/codegen_backend_arm_uops.c @@ -10,6 +10,7 @@ # include "x86.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" # include "386_common.h" # include "codegen.h" @@ -718,9 +719,9 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_arm_VCMP_D(block, src_reg_a, REG_D_TEMP); host_arm_MOV_IMM(block, dest_reg, 0); host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, FPU_SW_C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, FPU_SW_C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); } else fatal("codegen_FTST %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); @@ -758,9 +759,9 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) host_arm_VCMP_D(block, src_reg_a, src_reg_b); host_arm_MOV_IMM(block, dest_reg, 0); host_arm_VMRS_APSR(block); - host_arm_ORREQ_IMM(block, dest_reg, dest_reg, C3); - host_arm_ORRCC_IMM(block, dest_reg, dest_reg, C0); - host_arm_ORRVS_IMM(block, dest_reg, dest_reg, C0 | C2 | C3); + host_arm_ORREQ_IMM(block, dest_reg, dest_reg, FPU_SW_C3); + host_arm_ORRCC_IMM(block, dest_reg, dest_reg, FPU_SW_C0); + host_arm_ORRVS_IMM(block, dest_reg, dest_reg, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); } else fatal("codegen_FCOM %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real); diff --git a/src/codegen_new/codegen_backend_x86-64_uops.c b/src/codegen_new/codegen_backend_x86-64_uops.c index fcab0f3ce8..46af68e751 100644 --- a/src/codegen_new/codegen_backend_x86-64_uops.c +++ b/src/codegen_new/codegen_backend_x86-64_uops.c @@ -9,6 +9,7 @@ # include "x86.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "x87.h" # include "386_common.h" # include "codegen.h" @@ -672,7 +673,7 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); @@ -720,7 +721,7 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); diff --git a/src/codegen_new/codegen_backend_x86_uops.c b/src/codegen_new/codegen_backend_x86_uops.c index 5ef2d97b8a..cd79b9b47e 100644 --- a/src/codegen_new/codegen_backend_x86_uops.c +++ b/src/codegen_new/codegen_backend_x86_uops.c @@ -10,6 +10,7 @@ # include "x86_ops.h" # include "x86seg_common.h" # include "x86seg.h" +# include "x87_sf.h" # include "386_common.h" # include "codegen.h" # include "codegen_allocator.h" @@ -677,7 +678,7 @@ codegen_FTST(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, REG_XMM_TEMP); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); @@ -725,7 +726,7 @@ codegen_FCOM(codeblock_t *block, uop_t *uop) host_x86_XOR32_REG_REG(block, REG_EAX, REG_EAX); host_x86_COMISD_XREG_XREG(block, src_reg_a, src_reg_b); host_x86_LAHF(block); - host_x86_AND16_REG_IMM(block, REG_EAX, C0 | C2 | C3); + host_x86_AND16_REG_IMM(block, REG_EAX, FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (dest_reg != REG_EAX) { host_x86_MOV16_REG_REG(block, dest_reg, REG_EAX); host_x86_MOV32_REG_REG(block, REG_EAX, REG_ECX); diff --git a/src/codegen_new/codegen_block.c b/src/codegen_new/codegen_block.c index ee0a030ba9..a8ea0e06e6 100644 --- a/src/codegen_new/codegen_block.c +++ b/src/codegen_new/codegen_block.c @@ -12,6 +12,7 @@ #include "x86_ops.h" #include "x86seg_common.h" #include "x86seg.h" +#include "x87_sf.h" #include "x87.h" #include "386_common.h" diff --git a/src/codegen_new/codegen_ops_fpu_arith.c b/src/codegen_new/codegen_ops_fpu_arith.c index 3ab7be8ac9..a7b5290f4e 100644 --- a/src/codegen_new/codegen_ops_fpu_arith.c +++ b/src/codegen_new/codegen_ops_fpu_arith.c @@ -9,6 +9,7 @@ #include "x86seg_common.h" #include "x86seg.h" #include "386_common.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_accumulate.h" @@ -59,7 +60,7 @@ ropFCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); return op_pc; @@ -71,7 +72,7 @@ ropFCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fet uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP(block, ir); @@ -82,7 +83,7 @@ ropFCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe { uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP2(block, ir); @@ -269,7 +270,7 @@ ropFUCOM(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); return op_pc; @@ -281,7 +282,7 @@ ropFUCOMP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t fe uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP(block, ir); @@ -292,7 +293,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f { uop_FP_ENTER(ir); uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); fpu_POP2(block, ir); @@ -328,7 +329,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f codegen_check_seg_read(block, ir, target_seg); \ load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ \ return op_pc + 1; \ @@ -344,7 +345,7 @@ ropFUCOMPP(codeblock_t *block, ir_data_t *ir, UNUSED(uint8_t opcode), uint32_t f codegen_check_seg_read(block, ir, target_seg); \ load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ fpu_POP(block, ir); \ \ @@ -460,7 +461,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ \ return op_pc + 1; \ @@ -477,7 +478,7 @@ ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE) uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \ uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \ uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \ - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); \ + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); \ uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \ fpu_POP(block, ir); \ \ @@ -600,7 +601,7 @@ ropFTST(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), uint3 { uop_FP_ENTER(ir); uop_FTST(ir, IREG_temp0_W, IREG_ST(0)); - uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0 | C2 | C3)); + uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3)); uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W); return op_pc; diff --git a/src/codegen_new/codegen_ops_fpu_constant.c b/src/codegen_new/codegen_ops_fpu_constant.c index 8628458687..a91d675c5d 100644 --- a/src/codegen_new/codegen_ops_fpu_constant.c +++ b/src/codegen_new/codegen_ops_fpu_constant.c @@ -9,6 +9,7 @@ #include "x86seg_common.h" #include "x86seg.h" #include "386_common.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_accumulate.h" diff --git a/src/codegen_new/codegen_ops_fpu_loadstore.c b/src/codegen_new/codegen_ops_fpu_loadstore.c index 7635063e86..12babaf49d 100644 --- a/src/codegen_new/codegen_ops_fpu_loadstore.c +++ b/src/codegen_new/codegen_ops_fpu_loadstore.c @@ -9,6 +9,7 @@ #include "x86seg_common.h" #include "x86seg.h" #include "386_common.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_accumulate.h" diff --git a/src/codegen_new/codegen_ops_fpu_misc.c b/src/codegen_new/codegen_ops_fpu_misc.c index 7865e05730..31b668488e 100644 --- a/src/codegen_new/codegen_ops_fpu_misc.c +++ b/src/codegen_new/codegen_ops_fpu_misc.c @@ -9,6 +9,7 @@ #include "x86seg_common.h" #include "x86seg.h" #include "386_common.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_accumulate.h" diff --git a/src/config.c b/src/config.c index 77ec89125d..0153e20e88 100644 --- a/src/config.c +++ b/src/config.c @@ -431,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)) || @@ -452,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. */ @@ -551,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 @@ -792,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) { @@ -810,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); @@ -832,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); @@ -841,16 +861,46 @@ load_storage_controllers(void) cassette_enable = !!ini_section_get_int(cat, "cassette_enabled", 0); else cassette_enable = 0; + p = ini_section_get_string(cat, "cassette_file", ""); - if (strlen(p) > 511) - fatal("load_storage_controllers(): strlen(p) > 511\n"); - else - strncpy(cassette_fname, p, 511); + + if (!strcmp(p, usr_path)) + p[0] = 0x00; + + if (p[0] != 0x00) { + if (path_abs(p)) { + if (strlen(p) > 511) + fatal("load_storage_controllers(): strlen(p) > 511 (cassette_fname)\n"); + else + strncpy(cassette_fname, p, 511); + } else + path_append_filename(cassette_fname, usr_path, p); + path_normalize(cassette_fname); + } + p = ini_section_get_string(cat, "cassette_mode", ""); if (strlen(p) > 511) fatal("load_storage_controllers(): strlen(p) > 511\n"); else strncpy(cassette_mode, p, 511); + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + cassette_image_history[i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); + sprintf(temp, "cassette_image_history_%02i", i + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p) { + if (path_abs(p)) { + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("load_storage_controllers(): strlen(p) > 2047 " + "(cassette_image_history[%i])\n", i); + else + snprintf(cassette_image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s", p); + } else + snprintf(cassette_image_history[i], (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(cassette_image_history[i]); + } + } cassette_pos = ini_section_get_int(cat, "cassette_position", 0); cassette_srate = ini_section_get_int(cat, "cassette_srate", 44100); cassette_append = !!ini_section_get_int(cat, "cassette_append", 0); @@ -874,6 +924,24 @@ load_storage_controllers(void) path_append_filename(cart_fns[c], usr_path, p); path_normalize(cart_fns[c]); } + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + cart_image_history[c][i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); + sprintf(temp, "cartridge_%02i_image_history_%02i", c + 1, i + 1); + p = ini_section_get_string(cat, temp, NULL); + if (p) { + if (path_abs(p)) { + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("load_storage_controllers(): strlen(p) > 2047 " + "(cart_image_history[%i][%i])\n", c, i); + else + snprintf(cart_image_history[c][i], (MAX_IMAGE_PATH_LEN - 1), "%s", p); + } else + snprintf(cart_image_history[c][i], (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(cart_image_history[c][i]); + } + } } lba_enhancer_enabled = !!ini_section_get_int(cat, "lba_enhancer_enabled", 0); @@ -1611,7 +1679,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; @@ -1700,7 +1768,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) @@ -1927,7 +1995,7 @@ save_machine(void) else ini_section_delete_var(cat, "cpu_override"); if (cpu_override_interpreter) - ini_section_set_int(cat, "cpu_override_interpreter", cpu_override); + ini_section_set_int(cat, "cpu_override_interpreter", cpu_override_interpreter); else ini_section_delete_var(cat, "cpu_override_interpreter"); @@ -1993,10 +2061,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"); @@ -2273,14 +2344,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"); @@ -2307,14 +2378,32 @@ save_storage_controllers(void) if (strlen(cassette_fname) == 0) ini_section_delete_var(cat, "cassette_file"); - else - ini_section_set_string(cat, "cassette_file", cassette_fname); + else { + path_normalize(cassette_fname); + if (!strnicmp(cassette_fname, usr_path, strlen(usr_path))) + ini_section_set_string(cat, "cassette_file", &cassette_fname[strlen(usr_path)]); + else + ini_section_set_string(cat, "cassette_file", cassette_fname); + } if (strlen(cassette_mode) == 0) ini_section_delete_var(cat, "cassette_mode"); else ini_section_set_string(cat, "cassette_mode", cassette_mode); + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "cassette_image_history_%02i", i + 1); + if ((cassette_image_history[i] == 0) || strlen(cassette_image_history[i]) == 0) + ini_section_delete_var(cat, temp); + else { + path_normalize(cassette_image_history[i]); + if (!strnicmp(cassette_image_history[i], usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &cassette_image_history[i][strlen(usr_path)]); + else + ini_section_set_string(cat, temp, cassette_image_history[i]); + } + } + if (cassette_pos == 0) ini_section_delete_var(cat, "cassette_position"); else @@ -2342,10 +2431,29 @@ save_storage_controllers(void) for (c = 0; c < 2; c++) { sprintf(temp, "cartridge_%02i_fn", c + 1); + if (strlen(cart_fns[c]) == 0) ini_section_delete_var(cat, temp); - else - ini_section_set_string(cat, temp, cart_fns[c]); + else { + path_normalize(cart_fns[c]); + if (!strnicmp(cart_fns[c], usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &cart_fns[c][strlen(usr_path)]); + else + ini_section_set_string(cat, temp, cart_fns[c]); + } + + for (int i = 0; i < MAX_PREV_IMAGES; i++) { + sprintf(temp, "cartridge_%02i_image_history_%02i", c + 1, i + 1); + if ((cart_image_history[c][i] == 0) || strlen(cart_image_history[c][i]) == 0) + ini_section_delete_var(cat, temp); + else { + path_normalize(cart_image_history[c][i]); + if (!strnicmp(cart_image_history[c][i], usr_path, strlen(usr_path))) + ini_section_set_string(cat, temp, &cart_image_history[c][i][strlen(usr_path)]); + else + ini_section_set_string(cat, temp, cart_image_history[c][i]); + } + } } if (lba_enhancer_enabled == 0) diff --git a/src/cpu/386.c b/src/cpu/386.c index 5379dccf9b..8b612604df 100644 --- a/src/cpu/386.c +++ b/src/cpu/386.c @@ -15,6 +15,7 @@ #include "x86.h" #include "x86_ops.h" #include "x86seg_common.h" +#include "x87_sf.h" #include "x87.h" #include <86box/io.h> #include <86box/nmi.h> @@ -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. */ @@ -272,7 +279,7 @@ exec386_2386(int32_t cycs) if (!cpu_state.abrt) { #ifdef ENABLE_386_LOG if (in_smm) - x386_2386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat); + x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat); #endif opcode = fetchdat & 0xFF; fetchdat >>= 8; @@ -297,6 +304,13 @@ exec386_2386(int32_t cycs) cpu_state.pc &= 0xffff; #endif + if (cpu_flush_pending == 1) + cpu_flush_pending++; + else if (cpu_flush_pending == 2) { + cpu_flush_pending = 0; + flushmmucache_pc(); + } + if (cpu_end_block_after_ins) cpu_end_block_after_ins--; diff --git a/src/cpu/386_common.c b/src/cpu/386_common.c index f3926f1701..dcbe3608c6 100644 --- a/src/cpu/386_common.c +++ b/src/cpu/386_common.c @@ -14,6 +14,7 @@ #include <86box/timer.h> #include "x86.h" #include "x86seg_common.h" +#include "x87_sf.h" #include "x87.h" #include <86box/nmi.h> #include <86box/mem.h> @@ -50,6 +51,8 @@ uint32_t dr[8]; uint32_t use32; int stack32; +int cpu_init = 0; + uint32_t *eal_r; uint32_t *eal_w; @@ -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 */ @@ -426,42 +451,44 @@ x386_common_log(const char *fmt, ...) int is_lock_legal(uint32_t fetchdat) { - int legal; - fetch_dat_t fetch_dat; + int legal = 1; - fetch_dat.fd = fetchdat; + 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]]; + legal = lock_legal[fetch_dat.b[0]]; 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]; + 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,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]; + 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]; + 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]; + 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; + default: + legal = 0; break; + } } return legal; @@ -989,9 +1016,14 @@ smram_restore_state_p6(uint32_t *saved_state) cpu_state.seg_gs.ar_high = (saved_state[SMRAM_FIELD_P6_GS_SELECTOR_AR] >> 24) & 0xff; smm_seg_load(&cpu_state.seg_gs); - mem_a20_alt = 0x00; - mem_a20_key = saved_state[SMRAM_FIELD_P6_A20M] ? 0x00 : 0x02; - mem_a20_recalc(); + rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; + if (is6117) + rammask |= 0x3000000; + + if (saved_state[SMRAM_FIELD_P6_A20M] & 0x01) + rammask &= 0xffefffff; + + flushmmucache(); if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) smbase = saved_state[SMRAM_FIELD_P6_SMBASE_OFFSET]; diff --git a/src/cpu/386_common.h b/src/cpu/386_common.h index 6ef65771d4..ec40612ee3 100644 --- a/src/cpu/386_common.h +++ b/src/cpu/386_common.h @@ -449,6 +449,7 @@ get_ram_ptr(uint32_t a) } } +extern int opcode_has_modrm[256]; extern int opcode_length[256]; #ifdef OPS_286_386 @@ -457,6 +458,7 @@ fastreadw_fetch(uint32_t a) { uint16_t ret; + cpu_old_paging = (cpu_flush_pending == 2); if ((a & 0xFFF) > 0xFFE) { ret = fastreadb(a); if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 1)) @@ -468,6 +470,7 @@ fastreadw_fetch(uint32_t a) ret = readmemwl_2386(a); read_type = 4; } + cpu_old_paging = 0; return ret; } @@ -485,7 +488,9 @@ fastreadl_fetch(uint32_t a) ret = 0; else { read_type = 1; + cpu_old_paging = (cpu_flush_pending == 2); ret = readmemll_2386(a); + cpu_old_paging = 0; read_type = 4; } @@ -562,35 +567,52 @@ fastreadl_fetch(uint32_t a) } #endif +#ifdef OPS_286_386 static __inline uint8_t getbyte(void) { + uint8_t ret; cpu_state.pc++; - return fastreadb(cs + (cpu_state.pc - 1)); + cpu_old_paging = (cpu_flush_pending == 2); + ret = fastreadb(cs + (cpu_state.pc - 1)); + cpu_old_paging = 0; + return ret; + } static __inline uint16_t getword(void) { + uint16_t ret; cpu_state.pc += 2; - return fastreadw(cs + (cpu_state.pc - 2)); + cpu_old_paging = (cpu_flush_pending == 2); + ret = fastreadw(cs + (cpu_state.pc - 2)); + cpu_old_paging = 0; + return ret; } static __inline uint32_t getlong(void) { + uint32_t ret; cpu_state.pc += 4; - return fastreadl(cs + (cpu_state.pc - 4)); + cpu_old_paging = (cpu_flush_pending == 2); + ret = fastreadl(cs + (cpu_state.pc - 4)); + cpu_old_paging = 0; + return ret; } static __inline uint64_t getquad(void) { + uint64_t ret; cpu_state.pc += 8; - return fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32); + cpu_old_paging = (cpu_flush_pending == 2); + ret = fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32); + cpu_old_paging = 0; + return ret; } -#ifdef OPS_286_386 static __inline uint8_t geteab(void) { @@ -677,6 +699,34 @@ seteaq(uint64_t v) # define seteaw_mem(v) writememwl_2386(easeg + cpu_state.eaaddr, v); # define seteal_mem(v) writememll_2386(easeg + cpu_state.eaaddr, v); #else +static __inline uint8_t +getbyte(void) +{ + cpu_state.pc++; + return fastreadb(cs + (cpu_state.pc - 1)); +} + +static __inline uint16_t +getword(void) +{ + cpu_state.pc += 2; + return fastreadw(cs + (cpu_state.pc - 2)); +} + +static __inline uint32_t +getlong(void) +{ + cpu_state.pc += 4; + return fastreadl(cs + (cpu_state.pc - 4)); +} + +static __inline uint64_t +getquad(void) +{ + cpu_state.pc += 8; + return fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32); +} + static __inline uint8_t geteab(void) { diff --git a/src/cpu/386_dynarec.c b/src/cpu/386_dynarec.c index 77914a2a53..590d6f5c70 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu/386_dynarec.c @@ -19,6 +19,7 @@ #include "x86_ops.h" #include "x86seg_common.h" #include "x86seg.h" +#include "x87_sf.h" #include "x87.h" #include <86box/io.h> #include <86box/mem.h> @@ -349,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) @@ -413,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 @@ -590,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) @@ -687,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) @@ -766,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; @@ -917,6 +933,13 @@ exec386(int32_t cycs) x386_dynarec_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc); #endif + if (cpu_flush_pending == 1) + cpu_flush_pending++; + else if (cpu_flush_pending == 2) { + cpu_flush_pending = 0; + flushmmucache_pc(); + } + #ifndef USE_NEW_DYNAREC if (!use32) cpu_state.pc &= 0xffff; diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu/386_dynarec_ops.c index 066b00dd69..c31b725b23 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu/386_dynarec_ops.c @@ -15,6 +15,7 @@ #include "x86_ops.h" #include "x86seg_common.h" #include "x86seg.h" +#include "x87_sf.h" #include "x87.h" #include "x86_flags.h" #include <86box/io.h> diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h index 3e0d191f20..1301663443 100644 --- a/src/cpu/386_ops.h +++ b/src/cpu/386_ops.h @@ -1384,7 +1384,7 @@ const OpFn OP_TABLE(pentium_0f)[1024] = { // clang-format on }; -# if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +# ifdef USE_CYRIX_6X86 const OpFn OP_TABLE(c6x86_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ @@ -1476,7 +1476,7 @@ const OpFn OP_TABLE(c6x86_0f)[1024] = { /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, // clang-format on }; -# endif +# endif /* USE_CYRIX_6X86 */ const OpFn OP_TABLE(pentiummmx_0f)[1024] = { // clang-format off @@ -1754,7 +1754,7 @@ const OpFn OP_TABLE(k62_0f)[1024] = { // clang-format on }; -# if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +# ifdef USE_CYRIX_6X86 const OpFn OP_TABLE(c6x86mx_0f)[1024] = { // clang-format off /*16-bit data, 16-bit addr*/ @@ -1846,7 +1846,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] = { /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, // clang-format on }; -# endif +# endif /* USE_CYRIX_6X86 */ const OpFn OP_TABLE(pentiumpro_0f)[1024] = { // clang-format off diff --git a/src/cpu/808x.c b/src/cpu/808x.c index 5b411dd669..990f9ae87d 100644 --- a/src/cpu/808x.c +++ b/src/cpu/808x.c @@ -130,10 +130,10 @@ typedef int (*OpFn)(uint32_t fetchdat); static int tempc_fpu = 0; #ifdef ENABLE_808X_LOG +#if 0 void dumpregs(int); - +#endif int x808x_do_log = ENABLE_808X_LOG; -int indump = 0; static void x808x_log(const char *fmt, ...) @@ -785,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 diff --git a/src/cpu/CMakeLists.txt b/src/cpu/CMakeLists.txt index bd03a5558f..890d02e3e7 100644 --- a/src/cpu/CMakeLists.txt +++ b/src/cpu/CMakeLists.txt @@ -9,30 +9,61 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(cpu OBJECT cpu.c cpu_table.c fpu.c x86.c 808x.c 386.c 386_common.c - 386_dynarec.c x86_ops_mmx.c x86seg_common.c x86seg.c x86seg_2386.c x87.c - x87_timings.c 8080.c) +add_library(cpu OBJECT + cpu.c + cpu_table.c + fpu.c x86.c + 808x.c + 386.c + 386_common.c + 386_dynarec.c + x86_ops_mmx.c + x86seg_common.c + x86seg.c + x86seg_2386.c + x87.c + x87_timings.c + 8080.c +) if(AMD_K5) target_compile_definitions(cpu PRIVATE USE_AMD_K5) + +if(DYNAREC) + add_library(ctk5 OBJECT codegen_timing_k5.c) + target_link_libraries(86Box ctk5) +endif() + endif() if(CYRIX_6X86) target_compile_definitions(cpu PRIVATE USE_CYRIX_6X86) + +if(DYNAREC) + add_library(ct686 OBJECT codegen_timing_686.c) + target_link_libraries(86Box ct686) +endif() endif() if(DYNAREC) target_sources(cpu PRIVATE 386_dynarec_ops.c) - add_library(cgt OBJECT codegen_timing_486.c codegen_timing_686.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) + add_library(cgt OBJECT + codegen_timing_486.c + codegen_timing_common.c + codegen_timing_k6.c + codegen_timing_pentium.c + codegen_timing_p6.c + codegen_timing_winchip.c + codegen_timing_winchip2.c + ) endif() -add_subdirectory(softfloat) -target_link_libraries(86Box softfloat) +add_subdirectory(softfloat3e) +target_link_libraries(86Box softfloat3e) diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c index e862b123e7..90d6822110 100644 --- a/src/cpu/codegen_timing_486.c +++ b/src/cpu/codegen_timing_486.c @@ -9,6 +9,7 @@ #include "x86.h" #include "x86_ops.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_ops.h" @@ -17,7 +18,7 @@ #define CYCLES(c) (int *) c #define CYCLES2(c16, c32) (int *) ((-1 & ~0xffff) | c16 | (c32 << 8)) -static int *opcode_timings[256] = { +static int *opcode_timings_486[256] = { // clang-format off /*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), @@ -41,7 +42,7 @@ static int *opcode_timings[256] = { // clang-format on }; -static int *opcode_timings_mod3[256] = { +static int *opcode_timings_486_mod3[256] = { // clang-format off /*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), @@ -65,7 +66,7 @@ static int *opcode_timings_mod3[256] = { // clang-format on }; -static int *opcode_timings_0f[256] = { +static int *opcode_timings_486_0f[256] = { // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -88,7 +89,7 @@ static int *opcode_timings_0f[256] = { /*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, // clang-format on }; -static int *opcode_timings_0f_mod3[256] = { +static int *opcode_timings_486_0f_mod3[256] = { // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -112,65 +113,65 @@ static int *opcode_timings_0f_mod3[256] = { // clang-format on }; -static int *opcode_timings_shift[8] = { +static int *opcode_timings_486_shift[8] = { // clang-format off CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) }; -static int *opcode_timings_shift_mod3[8] = { +static int *opcode_timings_486_shift_mod3[8] = { // clang-format off CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) // clang-format on }; -static int *opcode_timings_f6[8] = { +static int *opcode_timings_486_f6[8] = { // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) // clang-format on }; -static int *opcode_timings_f6_mod3[8] = { +static int *opcode_timings_486_f6_mod3[8] = { // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) // clang-format on }; -static int *opcode_timings_f7[8] = { +static int *opcode_timings_486_f7[8] = { // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) // clang-format on }; -static int *opcode_timings_f7_mod3[8] = { +static int *opcode_timings_486_f7_mod3[8] = { // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) }; -static int *opcode_timings_ff[8] = { +static int *opcode_timings_486_ff[8] = { // clang-format off &timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL }; -static int *opcode_timings_ff_mod3[8] = { +static int *opcode_timings_486_ff_mod3[8] = { // clang-format off &timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL // clang-format on }; -static int *opcode_timings_d8[8] = { +static int *opcode_timings_486_d8[8] = { // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_d8_mod3[8] = { +static int *opcode_timings_486_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/ CYCLES(8), CYCLES(16), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_d9[8] = { +static int *opcode_timings_486_d9[8] = { // clang-format off /* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/ CYCLES(3), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3) // clang-format on }; -static int *opcode_timings_d9_mod3[64] = { +static int *opcode_timings_486_d9_mod3[64] = { // clang-format off /*FLD*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), @@ -191,25 +192,25 @@ static int *opcode_timings_d9_mod3[64] = { // clang-format on }; -static int *opcode_timings_da[8] = { +static int *opcode_timings_486_da[8] = { // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_da_mod3[8] = { +static int *opcode_timings_486_da_mod3[8] = { // clang-format off NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL // clang-format on }; -static int *opcode_timings_db[8] = { +static int *opcode_timings_486_db[8] = { // clang-format off /* FLDil FSTil FSTPil FLDe FSTPe*/ CYCLES(9), NULL, CYCLES(28), CYCLES(28), NULL, CYCLES(5), NULL, CYCLES(6) // clang-format on }; -static int *opcode_timings_db_mod3[64] = { +static int *opcode_timings_486_db_mod3[64] = { // clang-format off NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -223,74 +224,74 @@ static int *opcode_timings_db_mod3[64] = { // clang-format on }; -static int *opcode_timings_dc[8] = { +static int *opcode_timings_486_dc[8] = { // clang-format off /* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_dc_mod3[8] = { +static int *opcode_timings_486_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/ CYCLES(8), CYCLES(16), NULL, NULL, CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_dd[8] = { +static int *opcode_timings_486_dd[8] = { // clang-format off /* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/ CYCLES(3), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(3) // clang-format on }; -static int *opcode_timings_dd_mod3[8] = { +static int *opcode_timings_486_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL // clang-format on }; -static int *opcode_timings_de[8] = { +static int *opcode_timings_486_de[8] = { // clang-format off /* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_de_mod3[8] = { +static int *opcode_timings_486_de_mod3[8] = { // clang-format off /* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/ CYCLES(8), CYCLES(16), NULL, CYCLES(5), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73) // clang-format on }; -static int *opcode_timings_df[8] = { +static int *opcode_timings_486_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/ CYCLES(13), NULL, CYCLES(29), CYCLES(29), NULL, CYCLES(10), CYCLES(172), CYCLES(28) // clang-format on }; -static int *opcode_timings_df_mod3[8] = { +static int *opcode_timings_486_df_mod3[8] = { // clang-format off /* FFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL // clang-format on }; -static int *opcode_timings_8x[8] = { +static int *opcode_timings_486_8x[8] = { // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm // clang-format on }; -static int *opcode_timings_8x_mod3[8] = { +static int *opcode_timings_486_8x_mod3[8] = { // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm // clang-format on }; -static int *opcode_timings_81[8] = { +static int *opcode_timings_486_81[8] = { // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm // clang-format on }; -static int *opcode_timings_81_mod3[8] = { +static int *opcode_timings_486_81_mod3[8] = { // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm // clang-format on @@ -329,7 +330,7 @@ codegen_timing_486_start(void) void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat) { - timing_count += COUNT(opcode_timings[prefix], 0); + timing_count += COUNT(opcode_timings_486[prefix], 0); last_prefix = prefix; } @@ -343,47 +344,47 @@ codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(u switch (last_prefix) { case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + timings = mod3 ? opcode_timings_486_0f_mod3 : opcode_timings_486_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + timings = mod3 ? opcode_timings_486_d8_mod3 : opcode_timings_486_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + timings = mod3 ? opcode_timings_486_d9_mod3 : opcode_timings_486_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + timings = mod3 ? opcode_timings_486_da_mod3 : opcode_timings_486_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + timings = mod3 ? opcode_timings_486_db_mod3 : opcode_timings_486_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + timings = mod3 ? opcode_timings_486_dc_mod3 : opcode_timings_486_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + timings = mod3 ? opcode_timings_486_dd_mod3 : opcode_timings_486_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + timings = mod3 ? opcode_timings_486_de_mod3 : opcode_timings_486_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + timings = mod3 ? opcode_timings_486_df_mod3 : opcode_timings_486_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -393,12 +394,12 @@ codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(u case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + timings = mod3 ? opcode_timings_486_8x_mod3 : opcode_timings_486_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + timings = mod3 ? opcode_timings_486_81_mod3 : opcode_timings_486_81; deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; opcode = (fetchdat >> 3) & 7; break; @@ -409,29 +410,29 @@ codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(u case 0xd1: case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + timings = mod3 ? opcode_timings_486_shift_mod3 : opcode_timings_486_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + timings = mod3 ? opcode_timings_486_f6_mod3 : opcode_timings_486_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + timings = mod3 ? opcode_timings_486_f7_mod3 : opcode_timings_486_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + timings = mod3 ? opcode_timings_486_ff_mod3 : opcode_timings_486_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; + timings = mod3 ? opcode_timings_486_mod3 : opcode_timings_486; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c index a6800c5b22..285881956f 100644 --- a/src/cpu/codegen_timing_686.c +++ b/src/cpu/codegen_timing_686.c @@ -19,6 +19,7 @@ #include "x86.h" #include "x86_ops.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_timing_common.h" @@ -64,7 +65,7 @@ static uint32_t prev_fetchdat; static uint32_t last_regmask_modified; static uint32_t regmask_modified; -static uint32_t opcode_timings[256] = { +static uint32_t opcode_timings_686[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM, PAIR_XY | CYCLES_RM, @@ -201,7 +202,7 @@ static uint32_t opcode_timings[256] = { // clang-format on }; -static uint32_t opcode_timings_mod3[256] = { +static uint32_t opcode_timings_686_mod3[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, @@ -339,7 +340,7 @@ static uint32_t opcode_timings_mod3[256] = { // clang-format on }; -static uint32_t opcode_timings_0f[256] = { +static uint32_t opcode_timings_686_0f[256] = { // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -422,7 +423,7 @@ static uint32_t opcode_timings_0f[256] = { PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, PAIR_X | CYCLES_RM, INVALID, // clang-format on }; -static uint32_t opcode_timings_0f_mod3[256] = { +static uint32_t opcode_timings_686_0f_mod3[256] = { // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -505,44 +506,44 @@ static uint32_t opcode_timings_0f_mod3[256] = { // clang-format on }; -static uint32_t opcode_timings_shift[8] = { +static uint32_t opcode_timings_686_shift[8] = { // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, // clang-format on }; -static uint32_t opcode_timings_shift_mod3[8] = { +static uint32_t opcode_timings_686_shift_mod3[8] = { // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, // clang-format on }; -static uint32_t opcode_timings_shift_imm[8] = { +static uint32_t opcode_timings_686_shift_imm[8] = { // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, // clang-format on }; -static uint32_t opcode_timings_shift_imm_mod3[8] = { +static uint32_t opcode_timings_686_shift_imm_mod3[8] = { // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES(3), PAIR_XY | CYCLES(4), PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, // clang-format on }; -static uint32_t opcode_timings_shift_cl[8] = { +static uint32_t opcode_timings_686_shift_cl[8] = { // clang-format off PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), // clang-format on }; -static uint32_t opcode_timings_shift_cl_mod3[8] = { +static uint32_t opcode_timings_686_shift_cl_mod3[8] = { // clang-format off PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(8), PAIR_XY | CYCLES(9), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), PAIR_XY | CYCLES(2), // clang-format on }; -static uint32_t opcode_timings_f6[8] = { +static uint32_t opcode_timings_686_f6[8] = { // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_RM, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), @@ -550,7 +551,7 @@ static uint32_t opcode_timings_f6[8] = { PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) // clang-format on }; -static uint32_t opcode_timings_f6_mod3[8] = { +static uint32_t opcode_timings_686_f6_mod3[8] = { // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), @@ -558,7 +559,7 @@ static uint32_t opcode_timings_f6_mod3[8] = { PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(18), PAIR_NP | CYCLES(18) // clang-format on }; -static uint32_t opcode_timings_f7[8] = { +static uint32_t opcode_timings_686_f7[8] = { // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), @@ -566,7 +567,7 @@ static uint32_t opcode_timings_f7[8] = { PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) // clang-format on }; -static uint32_t opcode_timings_f7_mod3[8] = { +static uint32_t opcode_timings_686_f7_mod3[8] = { // clang-format off /* TST NOT NEG*/ PAIR_XY | CYCLES_REG, INVALID, PAIR_XY | CYCLES(1), PAIR_XY | CYCLES(1), @@ -574,7 +575,7 @@ static uint32_t opcode_timings_f7_mod3[8] = { PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(4,10), PAIR_NP | CYCLES_MULTI(19,27), PAIR_NP | CYCLES_MULTI(22,30) // clang-format on }; -static uint32_t opcode_timings_ff[8] = { +static uint32_t opcode_timings_686_ff[8] = { // clang-format off /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), @@ -582,7 +583,7 @@ static uint32_t opcode_timings_ff[8] = { PAIR_X_BRANCH | CYCLES(3), PAIR_NP | CYCLES(5), PAIR_XY | CYCLES(1), INVALID // clang-format on }; -static uint32_t opcode_timings_ff_mod3[8] = { +static uint32_t opcode_timings_686_ff_mod3[8] = { // clang-format off /* INC DEC CALL CALL far*/ PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_X_BRANCH | CYCLES(1), PAIR_XY | CYCLES(5), @@ -591,7 +592,7 @@ static uint32_t opcode_timings_ff_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_d8[8] = { +static uint32_t opcode_timings_686_d8[8] = { // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(6), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), @@ -599,7 +600,7 @@ static uint32_t opcode_timings_d8[8] = { PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) // clang-format on }; -static uint32_t opcode_timings_d8_mod3[8] = { +static uint32_t opcode_timings_686_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(6), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), @@ -608,7 +609,7 @@ static uint32_t opcode_timings_d8_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_d9[8] = { +static uint32_t opcode_timings_686_d9[8] = { // clang-format off /* FLDs FSTs FSTPs*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -616,7 +617,7 @@ static uint32_t opcode_timings_d9[8] = { PAIR_X | CYCLES(30), PAIR_X | CYCLES(4), PAIR_X | CYCLES(24), PAIR_X | CYCLES(5) // clang-format on }; -static uint32_t opcode_timings_d9_mod3[64] = { +static uint32_t opcode_timings_686_d9_mod3[64] = { // clang-format off /*FLD*/ PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -649,7 +650,7 @@ static uint32_t opcode_timings_d9_mod3[64] = { // clang-format on }; -static uint32_t opcode_timings_da[8] = { +static uint32_t opcode_timings_686_da[8] = { // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ PAIR_X | CYCLES(12), PAIR_X | CYCLES(11), PAIR_X | CYCLES(10), PAIR_X | CYCLES(10), @@ -657,14 +658,14 @@ static uint32_t opcode_timings_da[8] = { PAIR_X | CYCLES(29), PAIR_X | CYCLES(27), PAIR_X | CYCLES(38), PAIR_X | CYCLES(48) // clang-format on }; -static uint32_t opcode_timings_da_mod3[8] = { +static uint32_t opcode_timings_686_da_mod3[8] = { // clang-format off PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), INVALID, PAIR_X | CYCLES(5), INVALID, INVALID // clang-format on }; -static uint32_t opcode_timings_db[8] = { +static uint32_t opcode_timings_686_db[8] = { // clang-format off /* FLDil FSTil FSTPil*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -672,7 +673,7 @@ static uint32_t opcode_timings_db[8] = { INVALID, PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2) // clang-format on }; -static uint32_t opcode_timings_db_mod3[64] = { +static uint32_t opcode_timings_686_db_mod3[64] = { // clang-format off PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), PAIR_X | CYCLES(4), @@ -702,7 +703,7 @@ static uint32_t opcode_timings_db_mod3[64] = { // clang-format on }; -static uint32_t opcode_timings_dc[8] = { +static uint32_t opcode_timings_686_dc[8] = { // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), @@ -710,7 +711,7 @@ static uint32_t opcode_timings_dc[8] = { PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), PAIR_X | CYCLES(34), PAIR_X | CYCLES(34) // clang-format on }; -static uint32_t opcode_timings_dc_mod3[8] = { +static uint32_t opcode_timings_686_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), INVALID, INVALID, @@ -719,7 +720,7 @@ static uint32_t opcode_timings_dc_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_dd[8] = { +static uint32_t opcode_timings_686_dd[8] = { // clang-format off /* FLDd FSTd FSTPd*/ PAIR_X | CYCLES(2), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -727,7 +728,7 @@ static uint32_t opcode_timings_dd[8] = { PAIR_X | CYCLES(72), INVALID, PAIR_X | CYCLES(67), PAIR_X | CYCLES(2) // clang-format on }; -static uint32_t opcode_timings_dd_mod3[8] = { +static uint32_t opcode_timings_686_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP*/ PAIR_X | CYCLES(3), INVALID, PAIR_X | CYCLES(2), PAIR_X | CYCLES(2), @@ -736,14 +737,14 @@ static uint32_t opcode_timings_dd_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_de[8] = { +static uint32_t opcode_timings_686_de[8] = { // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ PAIR_X | CYCLES(12), PAIR_X | CYCLES(11), PAIR_X | CYCLES(10), PAIR_X | CYCLES(10), /* FISUBw FISUBRw FIDIVw FIDIVRw*/ PAIR_X | CYCLES(27), PAIR_X | CYCLES(27), PAIR_X | CYCLES(38), PAIR_X | CYCLES(38) }; -static uint32_t opcode_timings_de_mod3[8] = { +static uint32_t opcode_timings_686_de_mod3[8] = { // clang-format off /* FADD FMUL FCOMPP*/ PAIR_X | CYCLES(7), PAIR_X | CYCLES(7), INVALID, PAIR_X | CYCLES(7), @@ -752,7 +753,7 @@ static uint32_t opcode_timings_de_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_df[8] = { +static uint32_t opcode_timings_686_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw*/ PAIR_X | CYCLES(8), INVALID, PAIR_X | CYCLES(10), PAIR_X | CYCLES(13), @@ -760,7 +761,7 @@ static uint32_t opcode_timings_df[8] = { INVALID, PAIR_X | CYCLES(8), PAIR_X | CYCLES(63), PAIR_X | CYCLES(13) // clang-format on }; -static uint32_t opcode_timings_df_mod3[8] = { +static uint32_t opcode_timings_686_df_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ @@ -768,25 +769,25 @@ static uint32_t opcode_timings_df_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_8x[8] = { +static uint32_t opcode_timings_686_8x[8] = { // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM // clang-format on }; -static uint32_t opcode_timings_8x_mod3[8] = { +static uint32_t opcode_timings_686_8x_mod3[8] = { // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG // clang-format on }; -static uint32_t opcode_timings_81[8] = { +static uint32_t opcode_timings_686_81[8] = { // clang-format off PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RMW, PAIR_XY | CYCLES_RM // clang-format on }; -static uint32_t opcode_timings_81_mod3[8] = { +static uint32_t opcode_timings_686_81_mod3[8] = { // clang-format off PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG, PAIR_XY | CYCLES_REG @@ -873,47 +874,47 @@ codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(u switch (last_prefix) { case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + timings = mod3 ? opcode_timings_686_0f_mod3 : opcode_timings_686_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + timings = mod3 ? opcode_timings_686_d8_mod3 : opcode_timings_686_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + timings = mod3 ? opcode_timings_686_d9_mod3 : opcode_timings_686_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + timings = mod3 ? opcode_timings_686_da_mod3 : opcode_timings_686_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + timings = mod3 ? opcode_timings_686_db_mod3 : opcode_timings_686_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + timings = mod3 ? opcode_timings_686_dc_mod3 : opcode_timings_686_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + timings = mod3 ? opcode_timings_686_dd_mod3 : opcode_timings_686_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + timings = mod3 ? opcode_timings_686_de_mod3 : opcode_timings_686_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + timings = mod3 ? opcode_timings_686_df_mod3 : opcode_timings_686_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -923,55 +924,55 @@ codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(u case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + timings = mod3 ? opcode_timings_686_8x_mod3 : opcode_timings_686_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + timings = mod3 ? opcode_timings_686_81_mod3 : opcode_timings_686_81; deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; opcode = (fetchdat >> 3) & 7; break; case 0xc0: case 0xc1: - timings = mod3 ? opcode_timings_shift_imm_mod3 : opcode_timings_shift_imm; + timings = mod3 ? opcode_timings_686_shift_imm_mod3 : opcode_timings_686_shift_imm; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xd0: case 0xd1: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + timings = mod3 ? opcode_timings_686_shift_mod3 : opcode_timings_686_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_cl_mod3 : opcode_timings_shift_cl; + timings = mod3 ? opcode_timings_686_shift_cl_mod3 : opcode_timings_686_shift_cl; deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + timings = mod3 ? opcode_timings_686_f6_mod3 : opcode_timings_686_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + timings = mod3 ? opcode_timings_686_f7_mod3 : opcode_timings_686_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + timings = mod3 ? opcode_timings_686_ff_mod3 : opcode_timings_686_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; + timings = mod3 ? opcode_timings_686_mod3 : opcode_timings_686; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } diff --git a/src/cpu/codegen_timing_k5.c b/src/cpu/codegen_timing_k5.c new file mode 100644 index 0000000000..42b1129fe2 --- /dev/null +++ b/src/cpu/codegen_timing_k5.c @@ -0,0 +1,2232 @@ +/*Most of the vector instructions here are a total guess. + Some of the timings are based on https://web.archive.org/web/20181122095446/http://users.atw.hu/instlatx64/AuthenticAMD0000502_k5_InstLatX86.txt*/ +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/mem.h> +#include "cpu.h" +#include <86box/machine.h> + +#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" +#include "codegen_ops.h" +#include "codegen_timing_common.h" + +typedef enum uop_type_t { + UOP_ALU = 0, /*Executes in Integer X or Y units*/ + UOP_ALUX, /*Executes in Integer X unit*/ + UOP_LOAD, /*Executes in Load unit*/ + UOP_STORE, /*Executes in Store unit*/ + UOP_FLOAD, /*Executes in Load unit*/ + UOP_FSTORE, /*Executes in Store unit*/ + UOP_MLOAD, /*Executes in Load unit*/ + UOP_MSTORE, /*Executes in Store unit*/ + UOP_FLOAT, /*Executes in Floating Point unit*/ + UOP_MEU, /*Executes in Multimedia unit*/ + UOP_MEU_SHIFT, /*Executes in Multimedia unit or ALU X/Y. Uses MMX shifter*/ + UOP_MEU_MUL, /*Executes in Multimedia unit or ALU X/Y. Uses MMX/3DNow multiplier*/ + UOP_MEU_3DN, /*Executes in Multimedia unit or ALU X/Y. Uses 3DNow ALU*/ + UOP_BRANCH, /*Executes in Branch unit*/ + UOP_LIMM /*Does not require an execution unit*/ +} uop_type_t; + +typedef enum decode_type_t { + DECODE_SHORT, + DECODE_LONG, + DECODE_VECTOR +} decode_type_t; + +#define MAX_UOPS 10 + +typedef struct risc86_uop_t { + uop_type_t type; + int throughput; + int latency; +} risc86_uop_t; + +typedef struct risc86_instruction_t { + int nr_uops; + decode_type_t decode_type; + risc86_uop_t uop[MAX_UOPS]; +} risc86_instruction_t; + +static const risc86_instruction_t alu_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t alux_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_alu_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_alux_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t alu_store_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t alux_store_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t branch_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t limm_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LIMM, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t load_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2} +}; + +static const risc86_instruction_t store_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t bswap_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t leave_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t lods_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t loop_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mov_reg_seg_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, +}; +static const risc86_instruction_t movs_op = { + .nr_uops = 4, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t pop_reg_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t pop_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t push_imm_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2}, +}; +static const risc86_instruction_t push_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t push_seg_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t stos_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[1] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_reg_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_reg_b_op = { + .nr_uops = 1, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_mem_imm_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t test_mem_imm_b_op = { + .nr_uops = 2, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t xchg_op = { + .nr_uops = 3, + .decode_type = DECODE_LONG, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t m3dn_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_3DN, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mmx_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mmx_mul_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t mmx_shift_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_3dn_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_3DN, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_mmx_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t load_mmx_mul_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t load_mmx_shift_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_SHIFT, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t mload_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MLOAD, .throughput = 1, .latency = 2} +}; + +static const risc86_instruction_t mstore_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MSTORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t pmul_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t pmul_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_MEU_MUL, .throughput = 1, .latency = 2} +}; + +static const risc86_instruction_t float_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t load_float_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t fstore_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FSTORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t fdiv_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 40, .latency = 40} +}; +static const risc86_instruction_t fdiv_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_FLOAT, .throughput = 40, .latency = 40} +}; +static const risc86_instruction_t fsin_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 62, .latency = 62} +}; +static const risc86_instruction_t fsqrt_op = { + .nr_uops = 1, + .decode_type = DECODE_SHORT, + .uop[0] = {.type = UOP_FLOAT, .throughput = 41, .latency = 41} +}; + +static const risc86_instruction_t vector_fldcw_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 8, .latency = 8} +}; +static const risc86_instruction_t vector_float_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t vector_float_l_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 50, .latency = 50} +}; +static const risc86_instruction_t vector_flde_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_FLOAD, .throughput = 1, .latency = 2}, + .uop[2] = { .type = UOP_FLOAT, .throughput = 2, .latency = 2} +}; +static const risc86_instruction_t vector_fste_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_FLOAT, .throughput = 2, .latency = 2}, + .uop[1] = { .type = UOP_FSTORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_FSTORE, .throughput = 1, .latency = 1} +}; + +static const risc86_instruction_t vector_alu1_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu2_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu3_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu6_op = { + .nr_uops = 6, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux1_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux3_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux6_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alu_store_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_alux_store_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_arpl_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = { .type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_bound_op = { + .nr_uops = 4, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_bsx_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_call_far_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_cli_sti_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 7, .latency = 7} +}; +static const risc86_instruction_t vector_cmps_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_cmpsb_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_cmpxchg_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, +}; +static const risc86_instruction_t vector_cmpxchg_b_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, +}; +static const risc86_instruction_t vector_cpuid_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 22, .latency = 22} +}; +static const risc86_instruction_t vector_div16_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_div16_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALUX, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_div32_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 18, .latency = 18} +}; +static const risc86_instruction_t vector_div32_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALUX, .throughput = 18, .latency = 18} +}; +static const risc86_instruction_t vector_emms_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 25, .latency = 25} +}; +static const risc86_instruction_t vector_enter_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALU, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_femms_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 6, .latency = 6} +}; +static const risc86_instruction_t vector_in_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11} +}; +static const risc86_instruction_t vector_ins_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 10, .latency = 11}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1 } +}; +static const risc86_instruction_t vector_int_op = { + .nr_uops = 5, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 20, .latency = 20}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[3] = { .type = UOP_STORE, .throughput = 1, .latency = 1 }, + .uop[4] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1 } +}; +static const risc86_instruction_t vector_iret_op = { + .nr_uops = 5, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[2] = { .type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[3] = { .type = UOP_ALU, .throughput = 20, .latency = 20}, + .uop[4] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1 } +}; +static const risc86_instruction_t vector_invd_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1000, .latency = 1000} +}; +static const risc86_instruction_t vector_jmp_far_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_load_alu_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_load_alux_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_loop_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_lss_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[2] = { .type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_mov_mem_seg_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mov_seg_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_mov_seg_reg_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 3, .latency = 3} +}; +static const risc86_instruction_t vector_mul_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mul_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mul64_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_mul64_mem_op = { + .nr_uops = 4, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_out_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 10, .latency = 10} +}; +static const risc86_instruction_t vector_outs_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1 }, + .uop[1] = { .type = UOP_STORE, .throughput = 10, .latency = 10}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1 } +}; +static const risc86_instruction_t vector_pusha_op = { + .nr_uops = 8, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[6] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[7] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_popa_op = { + .nr_uops = 8, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[3] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[4] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[5] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[6] = { .type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[7] = { .type = UOP_LOAD, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_popf_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2 }, + .uop[1] = { .type = UOP_ALUX, .throughput = 17, .latency = 17} +}; +static const risc86_instruction_t vector_push_mem_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_pushf_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_ret_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_retf_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 3, .latency = 3}, + .uop[2] = { .type = UOP_BRANCH, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_scas_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_scasb_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_setcc_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_FSTORE, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_setcc_reg_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_test_mem_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_test_mem_b_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 2}, + .uop[1] = { .type = UOP_ALUX, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_xchg_mem_op = { + .nr_uops = 3, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_LOAD, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_STORE, .throughput = 1, .latency = 1}, + .uop[2] = { .type = UOP_ALU, .throughput = 1, .latency = 1} +}; +static const risc86_instruction_t vector_xlat_op = { + .nr_uops = 2, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 1, .latency = 1}, + .uop[1] = { .type = UOP_LOAD, .throughput = 1, .latency = 2} +}; +static const risc86_instruction_t vector_wbinvd_op = { + .nr_uops = 1, + .decode_type = DECODE_VECTOR, + .uop[0] = {.type = UOP_ALU, .throughput = 10000, .latency = 10000} +}; + +#define INVALID NULL + +static const risc86_instruction_t *opcode_timings_k5[256] = { + // clang-format off +/* ADD ADD ADD ADD*/ +/*00*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* ADD ADD PUSH ES POP ES*/ + &alux_op, &alu_op, &push_seg_op, &vector_mov_seg_mem_op, +/* OR OR OR OR*/ + &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* OR OR PUSH CS */ + &alux_op, &alu_op, &push_seg_op, INVALID, + +/* ADC ADC ADC ADC*/ +/*10*/ &vector_alux_store_op, &vector_alu_store_op, &vector_load_alux_op, &vector_load_alu_op, +/* ADC ADC PUSH SS POP SS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, +/* SBB SBB SBB SBB*/ +/*10*/ &vector_alux_store_op, &vector_alu_store_op, &vector_load_alux_op, &vector_load_alu_op, +/* SBB SBB PUSH DS POP DS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, + +/* AND AND AND AND*/ +/*20*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* AND AND DAA*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, +/* SUB SUB SUB SUB*/ + &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* SUB SUB DAS*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, + +/* XOR XOR XOR XOR*/ +/*30*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, +/* XOR XOR AAA*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, +/* CMP CMP CMP CMP*/ + &load_alux_op, &load_alu_op, &load_alux_op, &load_alu_op, +/* CMP CMP AAS*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, + +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ &alu_op, &alu_op, &alu_op, &alu_op, +/* INC ESP INC EBP INC ESI INC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, + +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ &store_op, &store_op, &store_op, &store_op, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + &store_op, &store_op, &store_op, &store_op, +/* POP EAX POP ECX POP EDX POP EBX*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, +/* POP ESP POP EBP POP ESI POP EDI*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, + +/* PUSHA POPA BOUND ARPL*/ +/*60*/ &vector_pusha_op, &vector_popa_op, &vector_bound_op, &vector_arpl_op, + INVALID, INVALID, INVALID, INVALID, +/* PUSH imm IMUL PUSH imm IMUL*/ + &push_imm_op, &vector_mul_op, &push_imm_op, &vector_mul_op, +/* INSB INSW OUTSB OUTSW*/ + &vector_ins_op, &vector_ins_op, &vector_outs_op, &vector_outs_op, + +/* Jxx*/ +/*70*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*80*/ INVALID, INVALID, INVALID, INVALID, +/* TEST TEST XCHG XCHG*/ + &vector_test_mem_b_op, &vector_test_mem_op, &vector_xchg_mem_op, &vector_xchg_mem_op, +/* MOV MOV MOV MOV*/ + &store_op, &store_op, &load_op, &load_op, +/* MOV from seg LEA MOV to seg POP*/ + &vector_mov_mem_seg_op, &store_op, &vector_mov_seg_mem_op, &pop_mem_op, + +/* NOP XCHG XCHG XCHG*/ +/*90*/ &limm_op, &xchg_op, &xchg_op, &xchg_op, +/* XCHG XCHG XCHG XCHG*/ + &xchg_op, &xchg_op, &xchg_op, &xchg_op, +/* CBW CWD CALL far WAIT*/ + &vector_alu1_op, &vector_alu1_op, &vector_call_far_op, &limm_op, +/* PUSHF POPF SAHF LAHF*/ + &vector_pushf_op, &vector_popf_op, &vector_alux1_op, &vector_alux1_op, + +/* MOV MOV MOV MOV*/ +/*a0*/ &load_op, &load_op, &store_op, &store_op, +/* MOVSB MOVSW CMPSB CMPSW*/ + &movs_op, &movs_op, &vector_cmpsb_op, &vector_cmps_op, +/* TEST TEST STOSB STOSW*/ + &test_reg_b_op, &test_reg_op, &stos_op, &stos_op, +/* LODSB LODSW SCASB SCASW*/ + &lods_op, &lods_op, &vector_scasb_op, &vector_scas_op, + +/* MOV*/ +/*b0*/ &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + +/* RET imm RET*/ +/*c0*/ INVALID, INVALID, &vector_ret_op, &vector_ret_op, +/* LES LDS MOV MOV*/ + &vector_lss_op, &vector_lss_op, &store_op, &store_op, +/* ENTER LEAVE RETF RETF*/ + &vector_enter_op, &leave_op, &vector_retf_op, &vector_retf_op, +/* INT3 INT INTO IRET*/ + &vector_int_op, &vector_int_op, &vector_int_op, &vector_iret_op, + + +/*d0*/ INVALID, INVALID, INVALID, INVALID, +/* AAM AAD SETALC XLAT*/ + &vector_alux6_op, &vector_alux3_op, &vector_alux1_op, &vector_xlat_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, +/* LOOPNE LOOPE LOOP JCXZ*/ +/*e0*/ &vector_loop_op, &vector_loop_op, &loop_op, &vector_loop_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, +/* CALL JMP JMP JMP*/ + &store_op, &branch_op, &vector_jmp_far_op, &branch_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, + +/* REPNE REPE*/ +/*f0*/ INVALID, INVALID, INVALID, INVALID, +/* HLT CMC*/ + &vector_alux1_op, &vector_alu2_op, INVALID, INVALID, +/* CLC STC CLI STI*/ + &vector_alu1_op, &vector_alu1_op, &vector_cli_sti_op, &vector_cli_sti_op, +/* CLD STD INCDEC*/ + &vector_alu1_op, &vector_alu1_op, &alux_store_op, INVALID + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_mod3[256] = { + // clang-format off +/* ADD ADD ADD ADD*/ +/*00*/ &alux_op, &alu_op, &alux_op, &alu_op, +/* ADD ADD PUSH ES POP ES*/ + &alux_op, &alu_op, &push_seg_op, &vector_mov_seg_mem_op, +/* OR OR OR OR*/ + &alux_op, &alu_op, &alux_op, &alu_op, +/* OR OR PUSH CS */ + &alux_op, &alu_op, &push_seg_op, INVALID, + +/* ADC ADC ADC ADC*/ +/*10*/ &vector_alux1_op, &vector_alu1_op, &vector_alux1_op, &vector_alu1_op, +/* ADC ADC PUSH SS POP SS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, +/* SBB SBB SBB SBB*/ + &vector_alux1_op, &vector_alu1_op, &vector_alux1_op, &vector_alu1_op, +/* SBB SBB PUSH DS POP DS*/ + &vector_alux1_op, &vector_alu1_op, &push_seg_op, &vector_mov_seg_mem_op, + +/* AND AND AND AND*/ +/*20*/ &alux_op, &alu_op, &alux_op, &alu_op, +/* AND AND DAA*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, +/* SUB SUB SUB SUB*/ + &alux_op, &alu_op, &alux_op, &alu_op, +/* SUB SUB DAS*/ + &alux_op, &alu_op, INVALID, &vector_alux1_op, + +/* XOR XOR XOR XOR*/ +/*30*/ &alux_op, &alu_op, &alux_op, &alu_op, +/* XOR XOR AAA*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, +/* CMP CMP CMP CMP*/ + &alux_op, &alu_op, &alux_op, &alu_op, +/* CMP CMP AAS*/ + &alux_op, &alu_op, INVALID, &vector_alux6_op, + +/* INC EAX INC ECX INC EDX INC EBX*/ +/*40*/ &alu_op, &alu_op, &alu_op, &alu_op, +/* INC ESP INC EBP INC ESI INC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC EAX DEC ECX DEC EDX DEC EBX*/ + &alu_op, &alu_op, &alu_op, &alu_op, +/* DEC ESP DEC EBP DEC ESI DEC EDI*/ + &alu_op, &alu_op, &alu_op, &alu_op, + +/* PUSH EAX PUSH ECX PUSH EDX PUSH EBX*/ +/*50*/ &store_op, &store_op, &store_op, &store_op, +/* PUSH ESP PUSH EBP PUSH ESI PUSH EDI*/ + &store_op, &store_op, &store_op, &store_op, +/* POP EAX POP ECX POP EDX POP EBX*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, +/* POP ESP POP EBP POP ESI POP EDI*/ + &pop_reg_op, &pop_reg_op, &pop_reg_op, &pop_reg_op, + +/* PUSHA POPA BOUND ARPL*/ +/*60*/ &vector_pusha_op, &vector_popa_op, &vector_bound_op, &vector_arpl_op, + INVALID, INVALID, INVALID, INVALID, +/* PUSH imm IMUL PUSH imm IMUL*/ + &push_imm_op, &vector_mul_op, &push_imm_op, &vector_mul_op, +/* INSB INSW OUTSB OUTSW*/ + &vector_ins_op, &vector_ins_op, &vector_outs_op, &vector_outs_op, + +/* Jxx*/ +/*70*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*80*/ INVALID, INVALID, INVALID, INVALID, +/* TEST TEST XCHG XCHG*/ + &vector_alu1_op, &vector_alu1_op, &vector_alu3_op, &vector_alu3_op, +/* MOV MOV MOV MOV*/ + &store_op, &store_op, &load_op, &load_op, +/* MOV from seg LEA MOV to seg POP*/ + &mov_reg_seg_op, &store_op, &vector_mov_seg_reg_op, &pop_reg_op, + +/* NOP XCHG XCHG XCHG*/ +/*90*/ &limm_op, &xchg_op, &xchg_op, &xchg_op, +/* XCHG XCHG XCHG XCHG*/ + &xchg_op, &xchg_op, &xchg_op, &xchg_op, +/* CBW CWD CALL far WAIT*/ + &vector_alu1_op, &vector_alu1_op, &vector_call_far_op, &limm_op, +/* PUSHF POPF SAHF LAHF*/ + &vector_pushf_op, &vector_popf_op, &vector_alux1_op, &vector_alux1_op, + +/* MOV MOV MOV MOV*/ +/*a0*/ &load_op, &load_op, &store_op, &store_op, +/* MOVSB MOVSW CMPSB CMPSW*/ + &movs_op, &movs_op, &vector_cmpsb_op, &vector_cmps_op, +/* TEST TEST STOSB STOSW*/ + &test_reg_b_op, &test_reg_op, &stos_op, &stos_op, +/* LODSB LODSW SCASB SCASW*/ + &lods_op, &lods_op, &vector_scasb_op, &vector_scas_op, + +/* MOV*/ +/*b0*/ &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + &limm_op, &limm_op, &limm_op, &limm_op, + +/* RET imm RET*/ +/*c0*/ INVALID, INVALID, &vector_ret_op, &vector_ret_op, +/* LES LDS MOV MOV*/ + &vector_lss_op, &vector_lss_op, &store_op, &store_op, +/* ENTER LEAVE RETF RETF*/ + &vector_enter_op, &leave_op, &vector_retf_op, &vector_retf_op, +/* INT3 INT INTO IRET*/ + &vector_int_op, &vector_int_op, &vector_int_op, &vector_iret_op, + + +/*d0*/ INVALID, INVALID, INVALID, INVALID, +/* AAM AAD SETALC XLAT*/ + &vector_alux6_op, &vector_alux3_op, &vector_alux1_op, &vector_xlat_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, +/* LOOPNE LOOPE LOOP JCXZ*/ +/*e0*/ &vector_loop_op, &vector_loop_op, &loop_op, &vector_loop_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, +/* CALL JMP JMP JMP*/ + &store_op, &branch_op, &vector_jmp_far_op, &branch_op, +/* IN AL IN AX OUT_AL OUT_AX*/ + &vector_in_op, &vector_in_op, &vector_out_op, &vector_out_op, + +/* REPNE REPE*/ +/*f0*/ INVALID, INVALID, INVALID, INVALID, +/* HLT CMC*/ + &vector_alux1_op, &vector_alu2_op, INVALID, INVALID, +/* CLC STC CLI STI*/ + &vector_alu1_op, &vector_alu1_op, &vector_cli_sti_op, &vector_cli_sti_op, +/* CLD STD INCDEC*/ + &vector_alu1_op, &vector_alu1_op, &vector_alux1_op, INVALID + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_0f[256] = { + // clang-format off +/*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, + &vector_invd_op, &vector_wbinvd_op, INVALID, INVALID, + INVALID, &load_op, &vector_femms_op, &load_3dn_op, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*20*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + &vector_alu6_op, &vector_alu6_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, + &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, + &load_mmx_op, &load_mmx_op, &load_mmx_op, &load_mmx_op, + INVALID, INVALID, &mload_op, &mload_op, + +/*70*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, + &load_mmx_op, &load_mmx_op, &load_mmx_op, &vector_emms_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, &mstore_op, &mstore_op, + +/*80*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*90*/ &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, &vector_setcc_reg_op, + +/*a0*/ &push_seg_op, &vector_mov_seg_mem_op, &vector_cpuid_op, &vector_load_alu_op, + &vector_alu_store_op, &vector_alu_store_op, INVALID, INVALID, + &push_seg_op, &vector_mov_seg_mem_op, INVALID, &vector_load_alu_op, + &vector_alu_store_op, &vector_alu_store_op, INVALID, &vector_mul_op, + +/*b0*/ &vector_cmpxchg_b_op, &vector_cmpxchg_op, &vector_lss_op, &vector_load_alu_op, + &vector_lss_op, &vector_lss_op, &load_alux_op, &load_alu_op, + INVALID, INVALID, &vector_load_alu_op, &vector_load_alu_op, + &vector_bsx_op, &vector_bsx_op, &load_alux_op, &load_alu_op, + +/*c0*/ &vector_alux_store_op, &vector_alu_store_op, INVALID, INVALID, + INVALID, INVALID, INVALID, &vector_cmpxchg_op, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + +/*d0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, + INVALID, &load_mmx_mul_op, INVALID, INVALID, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + +/*e0*/ &load_mmx_op, &load_mmx_shift_op, &load_mmx_shift_op, INVALID, + INVALID, &pmul_mem_op, INVALID, INVALID, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + &load_mmx_op, &load_mmx_op, INVALID, &load_mmx_op, + +/*f0*/ INVALID, &load_mmx_shift_op, &load_mmx_shift_op, &load_mmx_shift_op, + INVALID, &pmul_mem_op, INVALID, INVALID, + &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, + &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_0f_mod3[256] = { + // clang-format off +/*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, + &vector_invd_op, &vector_wbinvd_op, INVALID, INVALID, + INVALID, INVALID, &vector_femms_op, &m3dn_op, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*20*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, + &vector_alu6_op, &vector_alu6_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ &mmx_op, &mmx_op, &mmx_op, &mmx_op, + &mmx_op, &mmx_op, &mmx_op, &mmx_op, + &mmx_op, &mmx_op, &mmx_op, &mmx_op, + INVALID, INVALID, &mmx_op, &mmx_op, + +/*70*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, + &mmx_op, &mmx_op, &mmx_op, &vector_emms_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, &mmx_op, &mmx_op, + +/*80*/ &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + &branch_op, &branch_op, &branch_op, &branch_op, + +/*90*/ &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, &vector_setcc_mem_op, + +/*a0*/ &push_seg_op, &vector_mov_seg_mem_op, &vector_cpuid_op, &vector_alu1_op, + &vector_alu1_op, &vector_alu1_op, INVALID, INVALID, + &push_seg_op, &vector_mov_seg_mem_op, INVALID, &vector_alu1_op, + &vector_alu1_op, &vector_alu1_op, INVALID, &vector_mul_op, + +/*b0*/ &vector_cmpxchg_b_op, &vector_cmpxchg_op, &vector_lss_op, &vector_alu1_op, + &vector_lss_op, &vector_lss_op, &alux_op, &alu_op, + INVALID, INVALID, &vector_alu1_op, &vector_alu1_op, + &vector_bsx_op, &vector_bsx_op, &alux_op, &alu_op, + +/*c0*/ &vector_alux1_op, &vector_alu1_op, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + &bswap_op, &bswap_op, &bswap_op, &bswap_op, + +/*d0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, + INVALID, &mmx_mul_op, INVALID, INVALID, + &mmx_op, &mmx_op, INVALID, &mmx_op, + &mmx_op, &mmx_op, INVALID, &mmx_op, + +/*e0*/ &mmx_op, &mmx_shift_op, &mmx_shift_op, INVALID, + INVALID, &pmul_op, INVALID, INVALID, + &mmx_op, &mmx_op, INVALID, &mmx_op, + &mmx_op, &mmx_op, INVALID, &mmx_op, + +/*f0*/ INVALID, &mmx_shift_op, &mmx_shift_op, &mmx_shift_op, + INVALID, &pmul_op, INVALID, INVALID, + &mmx_op, &mmx_op, &mmx_op, INVALID, + &mmx_op, &mmx_op, &mmx_op, INVALID, + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_0f0f[256] = { + // clang-format off +/*00*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &load_3dn_op, INVALID, INVALID, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &load_3dn_op, INVALID, INVALID, + +/*20*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*70*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*80*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*90*/ &load_3dn_op, INVALID, INVALID, INVALID, + &load_3dn_op, INVALID, &load_3dn_op, &load_3dn_op, + INVALID, INVALID, &load_3dn_op, INVALID, + INVALID, INVALID, &load_3dn_op, INVALID, + +/*a0*/ &load_3dn_op, INVALID, INVALID, INVALID, + &load_3dn_op, INVALID, &load_mmx_mul_op, &load_mmx_mul_op, + INVALID, INVALID, &load_3dn_op, INVALID, + INVALID, INVALID, &load_3dn_op, INVALID, + +/*b0*/ &load_3dn_op, INVALID, INVALID, INVALID, + &load_mmx_mul_op, INVALID, &load_mmx_mul_op, &load_mmx_mul_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, &load_mmx_op, + +/*c0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*d0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*e0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*f0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_0f0f_mod3[256] = { + // clang-format off +/*00*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &m3dn_op, INVALID, INVALID, + +/*10*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, &m3dn_op, INVALID, INVALID, + +/*20*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*30*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*40*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*50*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*60*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*70*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*80*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*90*/ &m3dn_op, INVALID, INVALID, INVALID, + &m3dn_op, INVALID, &m3dn_op, &m3dn_op, + INVALID, INVALID, &m3dn_op, INVALID, + INVALID, INVALID, &m3dn_op, INVALID, + +/*a0*/ &m3dn_op, INVALID, INVALID, INVALID, + &m3dn_op, INVALID, &mmx_mul_op, &mmx_mul_op, + INVALID, INVALID, &m3dn_op, INVALID, + INVALID, INVALID, &m3dn_op, INVALID, + +/*b0*/ &m3dn_op, INVALID, INVALID, INVALID, + &mmx_mul_op, INVALID, &mmx_mul_op, &mmx_mul_op, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, &mmx_op, + +/*c0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*d0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*e0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/*f0*/ INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_shift[8] = { + // clang-format off + &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, + &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_shift_b[8] = { + // clang-format off + &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, + &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_shift_mod3[8] = { + // clang-format off + &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, + &alu_op, &alu_op, &alu_op, &alu_op + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_shift_b_mod3[8] = { + // clang-format off + &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, + &alux_op, &alux_op, &alux_op, &alux_op + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_80[8] = { + // clang-format off + &alux_store_op, &alux_store_op, &vector_alux_store_op, &vector_alux_store_op, + &alux_store_op, &alux_store_op, &alux_store_op, &alux_store_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_80_mod3[8] = { + // clang-format off + &alux_op, &alux_op, &alux_store_op, &alux_store_op, + &alux_op, &alux_op, &alux_op, &alux_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_8x[8] = { + // clang-format off + &alu_store_op, &alu_store_op, &vector_alu_store_op, &vector_alu_store_op, + &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_8x_mod3[8] = { + // clang-format off + &alu_op, &alu_op, &alu_store_op, &alu_store_op, + &alu_op, &alu_op, &alu_op, &alu_op, + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_f6[8] = { + // clang-format off +/* TST NOT NEG*/ + &test_mem_imm_b_op, INVALID, &vector_alux_store_op, &vector_alux_store_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul_mem_op, &vector_mul_mem_op, &vector_div16_mem_op, &vector_div16_mem_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_f6_mod3[8] = { + // clang-format off +/* TST NOT NEG*/ + &test_reg_b_op, INVALID, &alux_op, &alux_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul_op, &vector_mul_op, &vector_div16_op, &vector_div16_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_f7[8] = { + // clang-format off +/* TST NOT NEG*/ + &test_mem_imm_op, INVALID, &vector_alu_store_op, &vector_alu_store_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul64_mem_op, &vector_mul64_mem_op, &vector_div32_mem_op, &vector_div32_mem_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_f7_mod3[8] = { + // clang-format off +/* TST NOT NEG*/ + &test_reg_op, INVALID, &alu_op, &alu_op, +/* MUL IMUL DIV IDIV*/ + &vector_mul64_op, &vector_mul64_op, &vector_div32_op, &vector_div32_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_ff[8] = { + // clang-format off +/* INC DEC CALL CALL far*/ + &alu_store_op, &alu_store_op, &store_op, &vector_call_far_op, +/* JMP JMP far PUSH*/ + &branch_op, &vector_jmp_far_op, &push_mem_op, INVALID + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_ff_mod3[8] = { + // clang-format off +/* INC DEC CALL CALL far*/ + &vector_alu1_op, &vector_alu1_op, &store_op, &vector_call_far_op, +/* JMP JMP far PUSH*/ + &branch_op, &vector_jmp_far_op, &vector_push_mem_op, INVALID + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_d8[8] = { + // clang-format off +/* FADDs FMULs FCOMs FCOMPs*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FSUBs FSUBRs FDIVs FDIVRs*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_d8_mod3[8] = { + // clang-format off +/* FADD FMUL FCOM FCOMP*/ + &float_op, &float_op, &float_op, &float_op, +/* FSUB FSUBR FDIV FDIVR*/ + &float_op, &float_op, &fdiv_op, &fdiv_op, + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_d9[8] = { + // clang-format off +/* FLDs FSTs FSTPs*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FLDENV FLDCW FSTENV FSTCW*/ + &vector_float_l_op, &vector_fldcw_op, &vector_float_l_op, &vector_float_op + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_d9_mod3[64] = { + // clang-format off + /*FLD*/ + &float_op, &float_op, &float_op, &float_op, + &float_op, &float_op, &float_op, &float_op, + /*FXCH*/ + &float_op, &float_op, &float_op, &float_op, + &float_op, &float_op, &float_op, &float_op, + /*FNOP*/ + &float_op, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + /*FSTP*/ + &float_op, &float_op, &float_op, &float_op, + &float_op, &float_op, &float_op, &float_op, +/* opFCHS opFABS*/ + &float_op, &float_op, INVALID, INVALID, +/* opFTST opFXAM*/ + &float_op, &float_op, INVALID, INVALID, +/* opFLD1 opFLDL2T opFLDL2E opFLDPI*/ + &float_op, &float_op, &float_op, &float_op, +/* opFLDEG2 opFLDLN2 opFLDZ*/ + &float_op, &float_op, &float_op, INVALID, +/* opF2XM1 opFYL2X opFPTAN opFPATAN*/ + &fsin_op, &fsin_op, &fsin_op, &fsin_op, +/* opFDECSTP opFINCSTP,*/ + INVALID, INVALID, &float_op, &float_op, +/* opFPREM opFSQRT opFSINCOS*/ + &fdiv_op, INVALID, &fsqrt_op, &fsin_op, +/* opFRNDINT opFSCALE opFSIN opFCOS*/ + &float_op, &fdiv_op, &fsin_op, &fsin_op + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_da[8] = { + // clang-format off +/* FIADDl FIMULl FICOMl FICOMPl*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FISUBl FISUBRl FIDIVl FIDIVRl*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_da_mod3[8] = { + // clang-format off + INVALID, INVALID, INVALID, INVALID, +/* FCOMPP*/ + INVALID, &float_op, INVALID, INVALID + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_db[8] = { + // clang-format off +/* FLDil FSTil FSTPil*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FLDe FSTPe*/ + INVALID, &vector_flde_op, INVALID, &vector_fste_op + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_db_mod3[64] = { + // clang-format off + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + +/* opFNOP opFCLEX opFINIT*/ + INVALID, &float_op, &float_op, &float_op, +/* opFNOP opFNOP*/ + &float_op, &float_op, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + + INVALID, INVALID, INVALID, INVALID, + INVALID, INVALID, INVALID, INVALID, + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_dc[8] = { + // clang-format off +/* FADDd FMULd FCOMd FCOMPd*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FSUBd FSUBRd FDIVd FDIVRd*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_dc_mod3[8] = { + // clang-format off +/* opFADDr opFMULr*/ + &float_op, &float_op, INVALID, INVALID, +/* opFSUBRr opFSUBr opFDIVRr opFDIVr*/ + &float_op, &float_op, &fdiv_op, &fdiv_op + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_dd[8] = { + // clang-format off +/* FLDd FSTd FSTPd*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FRSTOR FSAVE FSTSW*/ + &vector_float_l_op, INVALID, &vector_float_l_op, &vector_float_l_op + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_dd_mod3[8] = { + // clang-format off +/* FFFREE FST FSTP*/ + &float_op, INVALID, &float_op, &float_op, +/* FUCOM FUCOMP*/ + &float_op, &float_op, INVALID, INVALID + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_de[8] = { + // clang-format off +/* FIADDw FIMULw FICOMw FICOMPw*/ + &load_float_op, &load_float_op, &load_float_op, &load_float_op, +/* FISUBw FISUBRw FIDIVw FIDIVRw*/ + &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_de_mod3[8] = { + // clang-format off +/* FADDP FMULP FCOMPP*/ + &float_op, &float_op, INVALID, &float_op, +/* FSUBP FSUBRP FDIVP FDIVRP*/ + &float_op, &float_op, &fdiv_op, &fdiv_op, + // clang-format on +}; + +static const risc86_instruction_t *opcode_timings_k5_df[8] = { + // clang-format off +/* FILDiw FISTiw FISTPiw*/ + &load_float_op, INVALID, &fstore_op, &fstore_op, +/* FILDiq FBSTP FISTPiq*/ + INVALID, &load_float_op, &vector_float_l_op, &fstore_op, + // clang-format on +}; +static const risc86_instruction_t *opcode_timings_k5_df_mod3[8] = { + // clang-format off + INVALID, INVALID, INVALID, INVALID, +/* FSTSW AX*/ + &float_op, INVALID, INVALID, INVALID + // clang-format on +}; + +static uint8_t last_prefix; +static int prefixes; + +static int decode_timestamp; +static int last_complete_timestamp; + +typedef struct k5_unit_t { + uint32_t uop_mask; + int first_available_cycle; +} k5_unit_t; + +static int nr_units; +static k5_unit_t *units; + +/*k5 has dedicated MMX unit*/ +static k5_unit_t k5_units[] = { + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX) }, /*Integer X*/ + { .uop_mask = (1 << UOP_ALU) }, /*Integer Y*/ + { .uop_mask = (1 << UOP_MEU) | (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) }, /*Multimedia*/ + { .uop_mask = (1 << UOP_FLOAT) }, /*Floating point*/ + { .uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD) }, /*Load*/ + { .uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE) }, /*Store*/ + { .uop_mask = (1 << UOP_BRANCH) } /*Branch*/ +}; +#define NR_k5_UNITS (sizeof(k5_units) / sizeof(k5_unit_t)) + +/*k5-2 and later integrate MMX into ALU X & Y, sharing multiplier, shifter and + 3DNow ALU between two execution units*/ +static k5_unit_t k5_2_units[] = { + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_ALUX) | (1 << UOP_MEU) | /*Integer X*/ + (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN) }, + { .uop_mask = (1 << UOP_ALU) | (1 << UOP_MEU) | /*Integer Y*/ + (1 << UOP_MEU_SHIFT) | (1 << UOP_MEU_MUL) | (1 << UOP_MEU_3DN) }, + { .uop_mask = (1 << UOP_FLOAT) }, /*Floating point*/ + { .uop_mask = (1 << UOP_LOAD) | (1 << UOP_FLOAD) | (1 << UOP_MLOAD) }, /*Load*/ + { .uop_mask = (1 << UOP_STORE) | (1 << UOP_FSTORE) | (1 << UOP_MSTORE) }, /*Store*/ + { .uop_mask = (1 << UOP_BRANCH) } /*Branch*/ +}; +#define NR_k5_2_UNITS (sizeof(k5_2_units) / sizeof(k5_unit_t)) + +/*First available cycles of shared execution units. Each of these can be submitted + to by ALU X and Y*/ +static int mul_first_available_cycle; +static int shift_first_available_cycle; +static int m3dnow_first_available_cycle; + +static int +uop_run(const risc86_uop_t *uop, int decode_time) +{ + k5_unit_t *best_unit = NULL; + int best_start_cycle = 99999; + + /*UOP_LIMM does not require execution*/ + if (uop->type == UOP_LIMM) + return decode_time; + + /*Handle shared units on k5-2 and later*/ + if (units == k5_2_units) { + if (uop->type == UOP_MEU_MUL && decode_time < mul_first_available_cycle) + decode_time = mul_first_available_cycle; + else if (uop->type == UOP_MEU_SHIFT && decode_time < mul_first_available_cycle) + decode_time = shift_first_available_cycle; + else if (uop->type == UOP_MEU_3DN && decode_time < mul_first_available_cycle) + decode_time = m3dnow_first_available_cycle; + } + + /*Find execution unit for this uOP*/ + for (int c = 0; c < nr_units; c++) { + if (units[c].uop_mask & (1 << uop->type)) { + if (units[c].first_available_cycle < best_start_cycle) { + best_unit = &units[c]; + best_start_cycle = units[c].first_available_cycle; + } + } + } + if (!best_unit) + fatal("uop_run: can not find execution unit\n"); + + if (best_start_cycle < decode_time) + best_start_cycle = decode_time; + best_unit->first_available_cycle = best_start_cycle + uop->throughput; + + if (units == k5_2_units) { + if (uop->type == UOP_MEU_MUL) + mul_first_available_cycle = best_start_cycle + uop->throughput; + else if (uop->type == UOP_MEU_SHIFT) + shift_first_available_cycle = best_start_cycle + uop->throughput; + else if (uop->type == UOP_MEU_3DN) + m3dnow_first_available_cycle = best_start_cycle + uop->throughput; + } + + return best_start_cycle + uop->throughput; +} + +/*The k5 decoder can decode, per clock : + - 1 or 2 'short' instructions, each up to 2 uOPs and 7 bytes long + - 1 'long' instruction, up to 4 uOPs + - 1 'vector' instruction, up to 4 uOPs per cycle, plus (I think) 1 cycle startup delay) +*/ +static struct { + int nr_uops; + const risc86_uop_t *uops[4]; + /*Earliest time a uop can start. If the timestamp is -1, then the uop is + part of a dependency chain and the start time is the completion time of + the previous uop*/ + int earliest_start[4]; +} decode_buffer; + +#define NR_OPQUADS 6 +/*Timestamps of when the last six opquads completed. The k5 scheduler retires + opquads in order, so this is needed to determine when the next can be scheduled*/ +static int opquad_completion_timestamp[NR_OPQUADS]; +static int next_opquad = 0; + +#define NR_REGS 8 +/*Timestamp of when last operation on an integer register completed*/ +static int reg_available_timestamp[NR_REGS]; +/*Timestamp of when last operation on an FPU register completed*/ +static int fpu_st_timestamp[8]; +/*Completion time of the last uop to be processed. Used to calculate timing of + dependent uop chains*/ +static int last_uop_timestamp = 0; + +void +decode_flush_k5(void) +{ + int uop_timestamp = 0; + + /*Decoded opquad can not be submitted if there are no free spaces in the + opquad buffer*/ + if (decode_timestamp < opquad_completion_timestamp[next_opquad]) + decode_timestamp = opquad_completion_timestamp[next_opquad]; + + /*Ensure that uops can not be submitted before they have been decoded*/ + if (decode_timestamp > last_uop_timestamp) + last_uop_timestamp = decode_timestamp; + + /*Submit uops to execution units, and determine the latest completion time*/ + for (int c = 0; c < decode_buffer.nr_uops; c++) { + int start_timestamp; + + if (decode_buffer.earliest_start[c] == -1) + start_timestamp = last_uop_timestamp; + else + start_timestamp = decode_buffer.earliest_start[c]; + + last_uop_timestamp = uop_run(decode_buffer.uops[c], start_timestamp); + if (last_uop_timestamp > uop_timestamp) + uop_timestamp = last_uop_timestamp; + } + + /*Calculate opquad completion time. Since opquads complete in order, it + must be after the last completion.*/ + if (uop_timestamp <= last_complete_timestamp) + last_complete_timestamp = last_complete_timestamp + 1; + else + last_complete_timestamp = uop_timestamp; + + /*Advance to next opquad in buffer*/ + opquad_completion_timestamp[next_opquad] = last_complete_timestamp; + next_opquad++; + if (next_opquad == NR_OPQUADS) + next_opquad = 0; + + decode_timestamp++; + decode_buffer.nr_uops = 0; +} + +/*The instruction is only of interest here if it's longer than 7 bytes, as that's the + limit on k5 short decoding*/ +static int +codegen_timing_instr_length(uint64_t deps, uint32_t fetchdat, int op_32) +{ + int len = prefixes + 1; /*Opcode*/ + if (deps & MODRM) { + len++; /*ModR/M*/ + if (deps & HAS_IMM8) + len++; + if (deps & HAS_IMM1632) + len += (op_32 & 0x100) ? 4 : 2; + + if (op_32 & 0x200) { + if ((fetchdat & 7) == 4 && (fetchdat & 0xc0) != 0xc0) { + /* Has SIB*/ + len++; + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0x700) == 0x500) + len += 4; + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 4; + else if ((fetchdat & 0xc7) == 0x05) + len += 4; + } + } else { + if ((fetchdat & 0xc0) == 0x40) + len++; + else if ((fetchdat & 0xc0) == 0x80) + len += 2; + else if ((fetchdat & 0xc7) == 0x06) + len += 2; + } + } + + return len; +} + +static void +decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetchdat, int op_32, int bit8) +{ + uint32_t regmask_required; + uint32_t regmask_modified; + int c; + int d; + int earliest_start = 0; + decode_type_t decode_type = ins->decode_type; + int instr_length = codegen_timing_instr_length(deps, fetchdat, op_32); + + /*Generate input register mask, and determine the earliest time this + instruction can start. This is not accurate, as this is calculated per + x86 instruction when it should be handled per uop*/ + regmask_required = get_dstdep_mask(deps, fetchdat, bit8); + regmask_required |= get_addr_regmask(deps, fetchdat, op_32); + for (c = 0; c < 8; c++) { + if (regmask_required & (1 << c)) { + if (reg_available_timestamp[c] > decode_timestamp) + earliest_start = reg_available_timestamp[c]; + } + } + if ((deps & FPU_RW_ST0) && fpu_st_timestamp[0] > decode_timestamp) + earliest_start = fpu_st_timestamp[0]; + if ((deps & FPU_RW_ST1) && fpu_st_timestamp[1] > decode_timestamp) + earliest_start = fpu_st_timestamp[1]; + if (deps & FPU_RW_STREG) { + int reg = fetchdat & 7; + + if (fpu_st_timestamp[reg] > decode_timestamp) + earliest_start = fpu_st_timestamp[reg]; + } + + /*Short decoders are limited to 7 bytes*/ + if (decode_type == DECODE_SHORT && instr_length > 7) + decode_type = DECODE_LONG; + /*Long decoder is limited to 11 bytes*/ + else if (instr_length > 11) + decode_type = DECODE_VECTOR; + + switch (decode_type) { + case DECODE_SHORT: + if (decode_buffer.nr_uops) { + decode_buffer.uops[decode_buffer.nr_uops] = &ins->uop[0]; + decode_buffer.earliest_start[decode_buffer.nr_uops] = earliest_start; + if (ins->nr_uops > 1) { + decode_buffer.uops[decode_buffer.nr_uops + 1] = &ins->uop[1]; + decode_buffer.earliest_start[decode_buffer.nr_uops + 1] = -1; + } + decode_buffer.nr_uops += ins->nr_uops; + + decode_flush_k5(); + } else { + decode_buffer.nr_uops = ins->nr_uops; + decode_buffer.uops[0] = &ins->uop[0]; + decode_buffer.earliest_start[0] = earliest_start; + if (ins->nr_uops > 1) { + decode_buffer.uops[1] = &ins->uop[1]; + decode_buffer.earliest_start[1] = -1; + } + } + break; + + case DECODE_LONG: + if (decode_buffer.nr_uops) + decode_flush_k5(); + + decode_buffer.nr_uops = ins->nr_uops; + for (c = 0; c < ins->nr_uops; c++) { + decode_buffer.uops[c] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[c] = earliest_start; + else + decode_buffer.earliest_start[c] = -1; + } + decode_flush_k5(); + break; + + case DECODE_VECTOR: + if (decode_buffer.nr_uops) + decode_flush_k5(); + + decode_timestamp++; + d = 0; + + for (c = 0; c < ins->nr_uops; c++) { + decode_buffer.uops[d] = &ins->uop[c]; + if (c == 0) + decode_buffer.earliest_start[d] = earliest_start; + else + decode_buffer.earliest_start[d] = -1; + d++; + + if (d == 4) { + d = 0; + decode_buffer.nr_uops = 4; + decode_flush_k5(); + } + } + if (d) { + decode_buffer.nr_uops = d; + decode_flush_k5(); + } + break; + } + + /*Update write timestamps for any output registers*/ + regmask_modified = get_dstdep_mask(deps, fetchdat, bit8); + for (c = 0; c < 8; c++) { + if (regmask_modified & (1 << c)) + reg_available_timestamp[c] = last_complete_timestamp; + } + if (deps & FPU_POP) { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c + 1]; + fpu_st_timestamp[7] = 0; + } + if (deps & FPU_POP2) { + for (c = 0; c < 6; c++) + fpu_st_timestamp[c] = fpu_st_timestamp[c + 2]; + fpu_st_timestamp[6] = fpu_st_timestamp[7] = 0; + } + if (deps & FPU_PUSH) { + for (c = 0; c < 7; c++) + fpu_st_timestamp[c + 1] = fpu_st_timestamp[c]; + fpu_st_timestamp[0] = 0; + } + if (deps & FPU_WRITE_ST0) + fpu_st_timestamp[0] = last_complete_timestamp; + if (deps & FPU_WRITE_ST1) + fpu_st_timestamp[1] = last_complete_timestamp; + if (deps & FPU_WRITE_STREG) { + int reg = fetchdat & 7; + if (deps & FPU_POP) + reg--; + if (reg >= 0 && !(reg == 0 && (deps & FPU_WRITE_ST0)) && !(reg == 1 && (deps & FPU_WRITE_ST1))) + fpu_st_timestamp[reg] = last_complete_timestamp; + } +} + +void +codegen_timing_k5_block_start(void) +{ + int c; + + for (c = 0; c < nr_units; c++) + units[c].first_available_cycle = 0; + + mul_first_available_cycle = 0; + shift_first_available_cycle = 0; + m3dnow_first_available_cycle = 0; + + decode_timestamp = 0; + last_complete_timestamp = 0; + + for (c = 0; c < NR_OPQUADS; c++) + opquad_completion_timestamp[c] = 0; + next_opquad = 0; + + for (c = 0; c < NR_REGS; c++) + reg_available_timestamp[c] = 0; + for (c = 0; c < 8; c++) + fpu_st_timestamp[c] = 0; +} + +void +codegen_timing_k5_start(void) +{ + if (cpu_s->cpu_type == CPU_K5) { + units = k5_units; + nr_units = NR_k5_UNITS; + } else { + units = k5_2_units; + nr_units = NR_k5_2_UNITS; + } + last_prefix = 0; + prefixes = 0; +} + +void +codegen_timing_k5_prefix(uint8_t prefix, uint32_t fetchdat) +{ + if (prefix != 0x0f) + decode_timestamp++; + + last_prefix = prefix; + prefixes++; +} + +void +codegen_timing_k5_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc) +{ + const risc86_instruction_t **ins_table; + const uint64_t *deps; + int mod3 = ((fetchdat & 0xc0) == 0xc0); + int old_last_complete_timestamp = last_complete_timestamp; + int bit8 = !(opcode & 1); + + switch (last_prefix) { + case 0x0f: + if (opcode == 0x0f) { + /*3DNow has the actual opcode after ModR/M, SIB and any offset*/ + uint32_t opcode_pc = op_pc + 1; /*Byte after ModR/M*/ + uint8_t modrm = fetchdat & 0xff; + uint8_t sib = (fetchdat >> 8) & 0xff; + + if ((modrm & 0xc0) != 0xc0) { + if (op_32 & 0x200) { + if ((modrm & 7) == 4) { + /* Has SIB*/ + opcode_pc++; + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((sib & 0x07) == 0x05) + opcode_pc += 4; + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 4; + else if ((modrm & 0xc7) == 0x05) + opcode_pc += 4; + } + } else { + if ((modrm & 0xc0) == 0x40) + opcode_pc++; + else if ((modrm & 0xc0) == 0x80) + opcode_pc += 2; + else if ((modrm & 0xc7) == 0x06) + opcode_pc += 2; + } + } + + opcode = fastreadb(cs + opcode_pc); + + ins_table = mod3 ? opcode_timings_k5_0f0f_mod3 : opcode_timings_k5_0f0f; + deps = mod3 ? opcode_deps_0f0f_mod3 : opcode_deps_0f0f; + } else { + ins_table = mod3 ? opcode_timings_k5_0f_mod3 : opcode_timings_k5_0f; + deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; + } + break; + + case 0xd8: + ins_table = mod3 ? opcode_timings_k5_d8_mod3 : opcode_timings_k5_d8; + deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; + opcode = (opcode >> 3) & 7; + break; + case 0xd9: + ins_table = mod3 ? opcode_timings_k5_d9_mod3 : opcode_timings_k5_d9; + deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xda: + ins_table = mod3 ? opcode_timings_k5_da_mod3 : opcode_timings_k5_da; + deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; + opcode = (opcode >> 3) & 7; + break; + case 0xdb: + ins_table = mod3 ? opcode_timings_k5_db_mod3 : opcode_timings_k5_db; + deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; + opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; + break; + case 0xdc: + ins_table = mod3 ? opcode_timings_k5_dc_mod3 : opcode_timings_k5_dc; + deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; + opcode = (opcode >> 3) & 7; + break; + case 0xdd: + ins_table = mod3 ? opcode_timings_k5_dd_mod3 : opcode_timings_k5_dd; + deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; + opcode = (opcode >> 3) & 7; + break; + case 0xde: + ins_table = mod3 ? opcode_timings_k5_de_mod3 : opcode_timings_k5_de; + deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; + opcode = (opcode >> 3) & 7; + break; + case 0xdf: + ins_table = mod3 ? opcode_timings_k5_df_mod3 : opcode_timings_k5_df; + deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; + opcode = (opcode >> 3) & 7; + break; + + default: + switch (opcode) { + case 0x80: + case 0x82: + ins_table = mod3 ? opcode_timings_k5_80_mod3 : opcode_timings_k5_80; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + case 0x81: + case 0x83: + ins_table = mod3 ? opcode_timings_k5_8x_mod3 : opcode_timings_k5_8x; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc0: + case 0xd0: + case 0xd2: + ins_table = mod3 ? opcode_timings_k5_shift_b_mod3 : opcode_timings_k5_shift_b; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xc1: + case 0xd1: + case 0xd3: + ins_table = mod3 ? opcode_timings_k5_shift_mod3 : opcode_timings_k5_shift; + deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; + opcode = (fetchdat >> 3) & 7; + break; + + case 0xf6: + ins_table = mod3 ? opcode_timings_k5_f6_mod3 : opcode_timings_k5_f6; + deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; + opcode = (fetchdat >> 3) & 7; + break; + case 0xf7: + ins_table = mod3 ? opcode_timings_k5_f7_mod3 : opcode_timings_k5_f7; + deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; + opcode = (fetchdat >> 3) & 7; + break; + case 0xff: + ins_table = mod3 ? opcode_timings_k5_ff_mod3 : opcode_timings_k5_ff; + deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; + opcode = (fetchdat >> 3) & 7; + break; + + default: + ins_table = mod3 ? opcode_timings_k5_mod3 : opcode_timings_k5; + deps = mod3 ? opcode_deps_mod3 : opcode_deps; + break; + } + } + + if (ins_table[opcode]) + decode_instruction(ins_table[opcode], deps[opcode], fetchdat, op_32, bit8); + else + decode_instruction(&vector_alu1_op, 0, fetchdat, op_32, bit8); + codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); +} + +void +codegen_timing_k5_block_end(void) +{ + if (decode_buffer.nr_uops) { + int old_last_complete_timestamp = last_complete_timestamp; + decode_flush_k5(); + codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); + } +} + +int +codegen_timing_k5_jump_cycles(void) +{ + if (decode_buffer.nr_uops) + return 1; + return 0; +} + +codegen_timing_t codegen_timing_k5 = { + codegen_timing_k5_start, + codegen_timing_k5_prefix, + codegen_timing_k5_opcode, + codegen_timing_k5_block_start, + codegen_timing_k5_block_end, + codegen_timing_k5_jump_cycles +}; diff --git a/src/cpu/codegen_timing_k6.c b/src/cpu/codegen_timing_k6.c index 4a9f23cd82..5566fbbcd8 100644 --- a/src/cpu/codegen_timing_k6.c +++ b/src/cpu/codegen_timing_k6.c @@ -1,5 +1,5 @@ /*Most of the vector instructions here are a total guess. - Some of the timings are based on http://http://web.archive.org/web/20181122095446/http://users.atw.hu/instlatx64/AuthenticAMD0000562_K6_InstLatX86.txt*/ + Some of the timings are based on https://web.archive.org/web/20181122095446/http://users.atw.hu/instlatx64/AuthenticAMD0000562_K6_InstLatX86.txt*/ #include #include #include @@ -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" @@ -758,7 +759,7 @@ static const risc86_instruction_t vector_wbinvd_op = { #define INVALID NULL -static const risc86_instruction_t *opcode_timings[256] = { +static const risc86_instruction_t *opcode_timings_k6[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alux_store_op, &alu_store_op, &load_alux_op, &load_alu_op, @@ -895,7 +896,7 @@ static const risc86_instruction_t *opcode_timings[256] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_mod3[256] = { +static const risc86_instruction_t *opcode_timings_k6_mod3[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alux_op, &alu_op, &alux_op, &alu_op, @@ -1032,7 +1033,7 @@ static const risc86_instruction_t *opcode_timings_mod3[256] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f[256] = { +static const risc86_instruction_t *opcode_timings_k6_0f[256] = { // clang-format off /*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, @@ -1115,7 +1116,7 @@ static const risc86_instruction_t *opcode_timings_0f[256] = { &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f_mod3[256] = { +static const risc86_instruction_t *opcode_timings_k6_0f_mod3[256] = { // clang-format off /*00*/ &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, &vector_alu6_op, INVALID, &vector_alu6_op, &vector_alu6_op, INVALID, @@ -1199,7 +1200,7 @@ static const risc86_instruction_t *opcode_timings_0f_mod3[256] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f0f[256] = { +static const risc86_instruction_t *opcode_timings_k6_0f0f[256] = { // clang-format off /*00*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1282,7 +1283,7 @@ static const risc86_instruction_t *opcode_timings_0f0f[256] = { INVALID, INVALID, INVALID, INVALID, // clang-format on }; -static const risc86_instruction_t *opcode_timings_0f0f_mod3[256] = { +static const risc86_instruction_t *opcode_timings_k6_0f0f_mod3[256] = { // clang-format off /*00*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1366,57 +1367,57 @@ static const risc86_instruction_t *opcode_timings_0f0f_mod3[256] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift[8] = { +static const risc86_instruction_t *opcode_timings_k6_shift[8] = { // clang-format off &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &vector_alu_store_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift_b[8] = { +static const risc86_instruction_t *opcode_timings_k6_shift_b[8] = { // clang-format off &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &vector_alux_store_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_shift_mod3[8] = { // clang-format off &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, &vector_alu1_op, &alu_op, &alu_op, &alu_op, &alu_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_shift_b_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_shift_b_mod3[8] = { // clang-format off &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, &vector_alux1_op, &alux_op, &alux_op, &alux_op, &alux_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_80[8] = { +static const risc86_instruction_t *opcode_timings_k6_80[8] = { // clang-format off &alux_store_op, &alux_store_op, &vector_alux_store_op, &vector_alux_store_op, &alux_store_op, &alux_store_op, &alux_store_op, &alux_store_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_80_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_80_mod3[8] = { // clang-format off &alux_op, &alux_op, &alux_store_op, &alux_store_op, &alux_op, &alux_op, &alux_op, &alux_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_8x[8] = { +static const risc86_instruction_t *opcode_timings_k6_8x[8] = { // clang-format off &alu_store_op, &alu_store_op, &vector_alu_store_op, &vector_alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_8x_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_8x_mod3[8] = { // clang-format off &alu_op, &alu_op, &alu_store_op, &alu_store_op, &alu_op, &alu_op, &alu_op, &alu_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_f6[8] = { +static const risc86_instruction_t *opcode_timings_k6_f6[8] = { // clang-format off /* TST NOT NEG*/ &test_mem_imm_b_op, INVALID, &vector_alux_store_op, &vector_alux_store_op, @@ -1424,7 +1425,7 @@ static const risc86_instruction_t *opcode_timings_f6[8] = { &vector_mul_mem_op, &vector_mul_mem_op, &vector_div16_mem_op, &vector_div16_mem_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_f6_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_f6_mod3[8] = { // clang-format off /* TST NOT NEG*/ &test_reg_b_op, INVALID, &alux_op, &alux_op, @@ -1432,7 +1433,7 @@ static const risc86_instruction_t *opcode_timings_f6_mod3[8] = { &vector_mul_op, &vector_mul_op, &vector_div16_op, &vector_div16_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_f7[8] = { +static const risc86_instruction_t *opcode_timings_k6_f7[8] = { // clang-format off /* TST NOT NEG*/ &test_mem_imm_op, INVALID, &vector_alu_store_op, &vector_alu_store_op, @@ -1440,7 +1441,7 @@ static const risc86_instruction_t *opcode_timings_f7[8] = { &vector_mul64_mem_op, &vector_mul64_mem_op, &vector_div32_mem_op, &vector_div32_mem_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_f7_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_f7_mod3[8] = { // clang-format off /* TST NOT NEG*/ &test_reg_op, INVALID, &alu_op, &alu_op, @@ -1448,7 +1449,7 @@ static const risc86_instruction_t *opcode_timings_f7_mod3[8] = { &vector_mul64_op, &vector_mul64_op, &vector_div32_op, &vector_div32_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_ff[8] = { +static const risc86_instruction_t *opcode_timings_k6_ff[8] = { // clang-format off /* INC DEC CALL CALL far*/ &alu_store_op, &alu_store_op, &store_op, &vector_call_far_op, @@ -1456,7 +1457,7 @@ static const risc86_instruction_t *opcode_timings_ff[8] = { &branch_op, &vector_jmp_far_op, &push_mem_op, INVALID // clang-format on }; -static const risc86_instruction_t *opcode_timings_ff_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_ff_mod3[8] = { // clang-format off /* INC DEC CALL CALL far*/ &vector_alu1_op, &vector_alu1_op, &store_op, &vector_call_far_op, @@ -1465,7 +1466,7 @@ static const risc86_instruction_t *opcode_timings_ff_mod3[8] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_d8[8] = { +static const risc86_instruction_t *opcode_timings_k6_d8[8] = { // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, @@ -1473,7 +1474,7 @@ static const risc86_instruction_t *opcode_timings_d8[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_d8_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP*/ &float_op, &float_op, &float_op, &float_op, @@ -1482,7 +1483,7 @@ static const risc86_instruction_t *opcode_timings_d8_mod3[8] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_d9[8] = { +static const risc86_instruction_t *opcode_timings_k6_d9[8] = { // clang-format off /* FLDs FSTs FSTPs*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1490,7 +1491,7 @@ static const risc86_instruction_t *opcode_timings_d9[8] = { &vector_float_l_op, &vector_fldcw_op, &vector_float_l_op, &vector_float_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_d9_mod3[64] = { +static const risc86_instruction_t *opcode_timings_k6_d9_mod3[64] = { // clang-format off /*FLD*/ &float_op, &float_op, &float_op, &float_op, @@ -1523,7 +1524,7 @@ static const risc86_instruction_t *opcode_timings_d9_mod3[64] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_da[8] = { +static const risc86_instruction_t *opcode_timings_k6_da[8] = { // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, @@ -1531,7 +1532,7 @@ static const risc86_instruction_t *opcode_timings_da[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_da_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_da_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ @@ -1539,7 +1540,7 @@ static const risc86_instruction_t *opcode_timings_da_mod3[8] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_db[8] = { +static const risc86_instruction_t *opcode_timings_k6_db[8] = { // clang-format off /* FLDil FSTil FSTPil*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1547,7 +1548,7 @@ static const risc86_instruction_t *opcode_timings_db[8] = { INVALID, &vector_flde_op, INVALID, &vector_fste_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_db_mod3[64] = { +static const risc86_instruction_t *opcode_timings_k6_db_mod3[64] = { // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1577,7 +1578,7 @@ static const risc86_instruction_t *opcode_timings_db_mod3[64] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_dc[8] = { +static const risc86_instruction_t *opcode_timings_k6_dc[8] = { // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, @@ -1585,7 +1586,7 @@ static const risc86_instruction_t *opcode_timings_dc[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_dc_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr*/ &float_op, &float_op, INVALID, INVALID, @@ -1594,7 +1595,7 @@ static const risc86_instruction_t *opcode_timings_dc_mod3[8] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_dd[8] = { +static const risc86_instruction_t *opcode_timings_k6_dd[8] = { // clang-format off /* FLDd FSTd FSTPd*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1602,7 +1603,7 @@ static const risc86_instruction_t *opcode_timings_dd[8] = { &vector_float_l_op, INVALID, &vector_float_l_op, &vector_float_l_op // clang-format on }; -static const risc86_instruction_t *opcode_timings_dd_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP*/ &float_op, INVALID, &float_op, &float_op, @@ -1611,7 +1612,7 @@ static const risc86_instruction_t *opcode_timings_dd_mod3[8] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_de[8] = { +static const risc86_instruction_t *opcode_timings_k6_de[8] = { // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ &load_float_op, &load_float_op, &load_float_op, &load_float_op, @@ -1619,7 +1620,7 @@ static const risc86_instruction_t *opcode_timings_de[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_de_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_de_mod3[8] = { // clang-format off /* FADDP FMULP FCOMPP*/ &float_op, &float_op, INVALID, &float_op, @@ -1628,7 +1629,7 @@ static const risc86_instruction_t *opcode_timings_de_mod3[8] = { // clang-format on }; -static const risc86_instruction_t *opcode_timings_df[8] = { +static const risc86_instruction_t *opcode_timings_k6_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1636,7 +1637,7 @@ static const risc86_instruction_t *opcode_timings_df[8] = { INVALID, &load_float_op, &vector_float_l_op, &fstore_op, // clang-format on }; -static const risc86_instruction_t *opcode_timings_df_mod3[8] = { +static const risc86_instruction_t *opcode_timings_k6_df_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ @@ -1768,7 +1769,7 @@ static int fpu_st_timestamp[8]; static int last_uop_timestamp = 0; void -decode_flush(void) +decode_flush_k6(void) { int uop_timestamp = 0; @@ -1907,7 +1908,7 @@ decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetc } decode_buffer.nr_uops += ins->nr_uops; - decode_flush(); + decode_flush_k6(); } else { decode_buffer.nr_uops = ins->nr_uops; decode_buffer.uops[0] = &ins->uop[0]; @@ -1921,7 +1922,7 @@ decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetc case DECODE_LONG: if (decode_buffer.nr_uops) - decode_flush(); + decode_flush_k6(); decode_buffer.nr_uops = ins->nr_uops; for (c = 0; c < ins->nr_uops; c++) { @@ -1931,12 +1932,12 @@ decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetc else decode_buffer.earliest_start[c] = -1; } - decode_flush(); + decode_flush_k6(); break; case DECODE_VECTOR: if (decode_buffer.nr_uops) - decode_flush(); + decode_flush_k6(); decode_timestamp++; d = 0; @@ -1952,12 +1953,12 @@ decode_instruction(const risc86_instruction_t *ins, uint64_t deps, uint32_t fetc if (d == 4) { d = 0; decode_buffer.nr_uops = 4; - decode_flush(); + decode_flush_k6(); } } if (d) { decode_buffer.nr_uops = d; - decode_flush(); + decode_flush_k6(); } break; } @@ -2093,51 +2094,51 @@ codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t opcode = fastreadb(cs + opcode_pc); - ins_table = mod3 ? opcode_timings_0f0f_mod3 : opcode_timings_0f0f; + ins_table = mod3 ? opcode_timings_k6_0f0f_mod3 : opcode_timings_k6_0f0f; deps = mod3 ? opcode_deps_0f0f_mod3 : opcode_deps_0f0f; } else { - ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + ins_table = mod3 ? opcode_timings_k6_0f_mod3 : opcode_timings_k6_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; } break; case 0xd8: - ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + ins_table = mod3 ? opcode_timings_k6_d8_mod3 : opcode_timings_k6_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + ins_table = mod3 ? opcode_timings_k6_d9_mod3 : opcode_timings_k6_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + ins_table = mod3 ? opcode_timings_k6_da_mod3 : opcode_timings_k6_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + ins_table = mod3 ? opcode_timings_k6_db_mod3 : opcode_timings_k6_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + ins_table = mod3 ? opcode_timings_k6_dc_mod3 : opcode_timings_k6_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + ins_table = mod3 ? opcode_timings_k6_dd_mod3 : opcode_timings_k6_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + ins_table = mod3 ? opcode_timings_k6_de_mod3 : opcode_timings_k6_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + ins_table = mod3 ? opcode_timings_k6_df_mod3 : opcode_timings_k6_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -2146,13 +2147,13 @@ codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t switch (opcode) { case 0x80: case 0x82: - ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; + ins_table = mod3 ? opcode_timings_k6_80_mod3 : opcode_timings_k6_80; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: case 0x83: - ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + ins_table = mod3 ? opcode_timings_k6_8x_mod3 : opcode_timings_k6_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; @@ -2160,7 +2161,7 @@ codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t case 0xc0: case 0xd0: case 0xd2: - ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; + ins_table = mod3 ? opcode_timings_k6_shift_b_mod3 : opcode_timings_k6_shift_b; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; @@ -2168,29 +2169,29 @@ codegen_timing_k6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t case 0xc1: case 0xd1: case 0xd3: - ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + ins_table = mod3 ? opcode_timings_k6_shift_mod3 : opcode_timings_k6_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + ins_table = mod3 ? opcode_timings_k6_f6_mod3 : opcode_timings_k6_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + ins_table = mod3 ? opcode_timings_k6_f7_mod3 : opcode_timings_k6_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + ins_table = mod3 ? opcode_timings_k6_ff_mod3 : opcode_timings_k6_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; + ins_table = mod3 ? opcode_timings_k6_mod3 : opcode_timings_k6; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } @@ -2208,7 +2209,7 @@ codegen_timing_k6_block_end(void) { if (decode_buffer.nr_uops) { int old_last_complete_timestamp = last_complete_timestamp; - decode_flush(); + decode_flush_k6(); codegen_block_cycles += (last_complete_timestamp - old_last_complete_timestamp); } } diff --git a/src/cpu/codegen_timing_p6.c b/src/cpu/codegen_timing_p6.c index 2c087ae86c..a228130686 100644 --- a/src/cpu/codegen_timing_p6.c +++ b/src/cpu/codegen_timing_p6.c @@ -13,6 +13,7 @@ #include "x86.h" #include "x86_ops.h" #include "x86seg_common.h" +#include "x87_sf.h" #include "x87.h" #include "386_common.h" #include "codegen.h" @@ -786,7 +787,7 @@ static const macro_op_t wbinvd_op = { }; #define INVALID NULL -static const macro_op_t *opcode_timings[256] = { +static const macro_op_t *opcode_timings_p6[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alup0_store_op, &alu_store_op, &load_alup0_op, &load_alu_op, @@ -923,7 +924,7 @@ static const macro_op_t *opcode_timings[256] = { // clang-format on }; -static const macro_op_t *opcode_timings_mod3[256] = { +static const macro_op_t *opcode_timings_p6_mod3[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ &alup0_op, &alu_op, &alup0_op, &alu_op, @@ -1061,7 +1062,7 @@ static const macro_op_t *opcode_timings_mod3[256] = { // clang-format on }; -static const macro_op_t *opcode_timings_0f[256] = { +static const macro_op_t *opcode_timings_p6_0f[256] = { // clang-format off /*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, INVALID, &alu6_op, &alu6_op, INVALID, @@ -1144,7 +1145,7 @@ static const macro_op_t *opcode_timings_0f[256] = { &load_mmx_op, &load_mmx_op, &load_mmx_op, INVALID, // clang-format on }; -static const macro_op_t *opcode_timings_0f_mod3[256] = { +static const macro_op_t *opcode_timings_p6_0f_mod3[256] = { // clang-format off /*00*/ &alu6_op, &alu6_op, &alu6_op, &alu6_op, INVALID, &alu6_op, &alu6_op, INVALID, @@ -1227,58 +1228,58 @@ static const macro_op_t *opcode_timings_0f_mod3[256] = { &mmx_op, &mmx_op, &mmx_op, INVALID, }; -static const macro_op_t *opcode_timings_shift[8] = +static const macro_op_t *opcode_timings_p6_shift[8] = { // clang-format off &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op // clang-format on }; -static const macro_op_t *opcode_timings_shift_b[8] = { +static const macro_op_t *opcode_timings_p6_shift_b[8] = { // clang-format off &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op // clang-format on }; -static const macro_op_t *opcode_timings_shift_mod3[8] = { +static const macro_op_t *opcode_timings_p6_shift_mod3[8] = { // clang-format off &complex_alu1_op, &complex_alu1_op, &complex_alu1_op, &complex_alu1_op, &alu_op, &alu_op, &alu_op, &alu_op // clang-format on }; -static const macro_op_t *opcode_timings_shift_b_mod3[8] = { +static const macro_op_t *opcode_timings_p6_shift_b_mod3[8] = { // clang-format off &complex_alup0_1_op, &complex_alup0_1_op, &complex_alup0_1_op, &complex_alup0_1_op, &alup0_op, &alup0_op, &alup0_op, &alup0_op // clang-format on }; -static const macro_op_t *opcode_timings_80[8] = { +static const macro_op_t *opcode_timings_p6_80[8] = { // clang-format off &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, &alup0_store_op, // clang-format on }; -static const macro_op_t *opcode_timings_80_mod3[8] = { +static const macro_op_t *opcode_timings_p6_80_mod3[8] = { // clang-format off &alup0_op, &alup0_op, &alup0_store_op, &alup0_store_op, &alup0_op, &alup0_op, &alup0_op, &alup0_op, // clang-format on }; -static const macro_op_t *opcode_timings_8x[8] = { +static const macro_op_t *opcode_timings_p6_8x[8] = { // clang-format off &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, &alu_store_op, // clang-format on }; -static const macro_op_t *opcode_timings_8x_mod3[8] = { +static const macro_op_t *opcode_timings_p6_8x_mod3[8] = { // clang-format off &alu_op, &alu_op, &alu_store_op, &alu_store_op, &alu_op, &alu_op, &alu_op, &alu_op, // clang-format on }; -static const macro_op_t *opcode_timings_f6[8] = { +static const macro_op_t *opcode_timings_p6_f6[8] = { // clang-format off /* TST NOT NEG*/ &test_mem_imm_b_op, INVALID, &alup0_store_op, &alup0_store_op, @@ -1286,7 +1287,7 @@ static const macro_op_t *opcode_timings_f6[8] = { &mul_mem_op, &mul_mem_op, &div16_mem_op, &div16_mem_op, // clang-format on }; -static const macro_op_t *opcode_timings_f6_mod3[8] = { +static const macro_op_t *opcode_timings_p6_f6_mod3[8] = { // clang-format off /* TST NOT NEG*/ &test_reg_b_op, INVALID, &alup0_op, &alup0_op, @@ -1294,7 +1295,7 @@ static const macro_op_t *opcode_timings_f6_mod3[8] = { &mul_op, &mul_op, &div16_op, &div16_op, // clang-format on }; -static const macro_op_t *opcode_timings_f7[8] = { +static const macro_op_t *opcode_timings_p6_f7[8] = { // clang-format off /* TST NOT NEG*/ &test_mem_imm_op, INVALID, &alu_store_op, &alu_store_op, @@ -1302,7 +1303,7 @@ static const macro_op_t *opcode_timings_f7[8] = { &mul64_mem_op, &mul64_mem_op, &div32_mem_op, &div32_mem_op, // clang-format on }; -static const macro_op_t *opcode_timings_f7_mod3[8] = { +static const macro_op_t *opcode_timings_p6_f7_mod3[8] = { // clang-format off /* TST NOT NEG*/ &test_reg_op, INVALID, &alu_op, &alu_op, @@ -1310,7 +1311,7 @@ static const macro_op_t *opcode_timings_f7_mod3[8] = { &mul64_op, &mul64_op, &div32_op, &div32_op, // clang-format on }; -static const macro_op_t *opcode_timings_ff[8] = { +static const macro_op_t *opcode_timings_p6_ff[8] = { // clang-format off /* INC DEC CALL CALL far*/ &alu_store_op, &alu_store_op, &store_op, &call_far_op, @@ -1318,7 +1319,7 @@ static const macro_op_t *opcode_timings_ff[8] = { &branch_op, &jmp_far_op, &push_mem_op, INVALID // clang-format on }; -static const macro_op_t *opcode_timings_ff_mod3[8] = { +static const macro_op_t *opcode_timings_p6_ff_mod3[8] = { // clang-format off /* INC DEC CALL CALL far*/ &complex_alu1_op, &complex_alu1_op, &store_op, &call_far_op, @@ -1327,7 +1328,7 @@ static const macro_op_t *opcode_timings_ff_mod3[8] = { // clang-format on }; -static const macro_op_t *opcode_timings_d8[8] = { +static const macro_op_t *opcode_timings_p6_d8[8] = { // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ &load_fadd_op, &load_fmul_op, &load_float_op, &load_float_op, @@ -1335,7 +1336,7 @@ static const macro_op_t *opcode_timings_d8[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const macro_op_t *opcode_timings_d8_mod3[8] = { +static const macro_op_t *opcode_timings_p6_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP*/ &fadd_op, &fmul_op, &float_op, &float_op, @@ -1344,7 +1345,7 @@ static const macro_op_t *opcode_timings_d8_mod3[8] = { // clang-format on }; -static const macro_op_t *opcode_timings_d9[8] = { +static const macro_op_t *opcode_timings_p6_d9[8] = { // clang-format off /* FLDs FSTs FSTPs*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1352,7 +1353,7 @@ static const macro_op_t *opcode_timings_d9[8] = { &complex_float_l_op, &fldcw_op, &complex_float_l_op, &complex_float_op // clang-format on }; -static const macro_op_t *opcode_timings_d9_mod3[64] = { +static const macro_op_t *opcode_timings_p6_d9_mod3[64] = { // clang-format off /*FLD*/ &float_op, &float_op, &float_op, &float_op, @@ -1385,7 +1386,7 @@ static const macro_op_t *opcode_timings_d9_mod3[64] = { // clang-format on }; -static const macro_op_t *opcode_timings_da[8] = { +static const macro_op_t *opcode_timings_p6_da[8] = { // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ &load_fadd_op, &load_fmul_op, &load_float_op, &load_float_op, @@ -1393,7 +1394,7 @@ static const macro_op_t *opcode_timings_da[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const macro_op_t *opcode_timings_da_mod3[8] = { +static const macro_op_t *opcode_timings_p6_da_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ @@ -1401,7 +1402,7 @@ static const macro_op_t *opcode_timings_da_mod3[8] = { // clang-format on }; -static const macro_op_t *opcode_timings_db[8] = { +static const macro_op_t *opcode_timings_p6_db[8] = { // clang-format off /* FLDil FSTil FSTPil*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1409,7 +1410,7 @@ static const macro_op_t *opcode_timings_db[8] = { INVALID, &flde_op, INVALID, &fste_op // clang-format on }; -static const macro_op_t *opcode_timings_db_mod3[64] = { +static const macro_op_t *opcode_timings_p6_db_mod3[64] = { // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -1439,7 +1440,7 @@ static const macro_op_t *opcode_timings_db_mod3[64] = { // clang-format on }; -static const macro_op_t *opcode_timings_dc[8] = { +static const macro_op_t *opcode_timings_p6_dc[8] = { // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ &load_fadd_op, &load_fmul_op, &load_float_op, &load_float_op, @@ -1447,7 +1448,7 @@ static const macro_op_t *opcode_timings_dc[8] = { &load_float_op, &load_float_op, &fdiv_mem_op, &fdiv_mem_op, // clang-format on }; -static const macro_op_t *opcode_timings_dc_mod3[8] = { +static const macro_op_t *opcode_timings_p6_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr*/ &fadd_op, &fmul_op, INVALID, INVALID, @@ -1456,7 +1457,7 @@ static const macro_op_t *opcode_timings_dc_mod3[8] = { // clang-format on }; -static const macro_op_t *opcode_timings_dd[8] = { +static const macro_op_t *opcode_timings_p6_dd[8] = { // clang-format off /* FLDd FSTd FSTPd*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1464,7 +1465,7 @@ static const macro_op_t *opcode_timings_dd[8] = { &complex_float_l_op, INVALID, &complex_float_l_op, &complex_float_l_op // clang-format on }; -static const macro_op_t *opcode_timings_dd_mod3[8] = { +static const macro_op_t *opcode_timings_p6_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP*/ &float_op, INVALID, &float_op, &float_op, @@ -1473,7 +1474,7 @@ static const macro_op_t *opcode_timings_dd_mod3[8] = { // clang-format on }; -static const macro_op_t *opcode_timings_de[8] = { +static const macro_op_t *opcode_timings_p6_de[8] = { // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, @@ -1481,7 +1482,7 @@ static const macro_op_t *opcode_timings_de[8] = { &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, &load_fiadd_op, // clang-format on }; -static const macro_op_t *opcode_timings_de_mod3[8] = { +static const macro_op_t *opcode_timings_p6_de_mod3[8] = { // clang-format off /* FADDP FMULP FCOMPP*/ &fadd_op, &fmul_op, INVALID, &float_op, @@ -1490,7 +1491,7 @@ static const macro_op_t *opcode_timings_de_mod3[8] = { // clang-format on }; -static const macro_op_t *opcode_timings_df[8] = { +static const macro_op_t *opcode_timings_p6_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw*/ &load_float_op, INVALID, &fstore_op, &fstore_op, @@ -1498,7 +1499,7 @@ static const macro_op_t *opcode_timings_df[8] = { INVALID, &load_float_op, &complex_float_l_op, &fstore_op, // clang-format on }; -static const macro_op_t *opcode_timings_df_mod3[8] = { +static const macro_op_t *opcode_timings_p6_df_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ @@ -1864,47 +1865,47 @@ codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(ui switch (last_prefix) { case 0x0f: - ins_table = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + ins_table = mod3 ? opcode_timings_p6_0f_mod3 : opcode_timings_p6_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: - ins_table = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + ins_table = mod3 ? opcode_timings_p6_d8_mod3 : opcode_timings_p6_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - ins_table = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + ins_table = mod3 ? opcode_timings_p6_d9_mod3 : opcode_timings_p6_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - ins_table = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + ins_table = mod3 ? opcode_timings_p6_da_mod3 : opcode_timings_p6_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - ins_table = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + ins_table = mod3 ? opcode_timings_p6_db_mod3 : opcode_timings_p6_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - ins_table = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + ins_table = mod3 ? opcode_timings_p6_dc_mod3 : opcode_timings_p6_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - ins_table = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + ins_table = mod3 ? opcode_timings_p6_dd_mod3 : opcode_timings_p6_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - ins_table = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + ins_table = mod3 ? opcode_timings_p6_de_mod3 : opcode_timings_p6_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - ins_table = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + ins_table = mod3 ? opcode_timings_p6_df_mod3 : opcode_timings_p6_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -1913,13 +1914,13 @@ codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(ui switch (opcode) { case 0x80: case 0x82: - ins_table = mod3 ? opcode_timings_80_mod3 : opcode_timings_80; + ins_table = mod3 ? opcode_timings_p6_80_mod3 : opcode_timings_p6_80; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: case 0x83: - ins_table = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + ins_table = mod3 ? opcode_timings_p6_8x_mod3 : opcode_timings_p6_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; @@ -1927,7 +1928,7 @@ codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(ui case 0xc0: case 0xd0: case 0xd2: - ins_table = mod3 ? opcode_timings_shift_b_mod3 : opcode_timings_shift_b; + ins_table = mod3 ? opcode_timings_p6_shift_b_mod3 : opcode_timings_p6_shift_b; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; @@ -1935,29 +1936,29 @@ codegen_timing_p6_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUSED(ui case 0xc1: case 0xd1: case 0xd3: - ins_table = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + ins_table = mod3 ? opcode_timings_p6_shift_mod3 : opcode_timings_p6_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - ins_table = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + ins_table = mod3 ? opcode_timings_p6_f6_mod3 : opcode_timings_p6_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - ins_table = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + ins_table = mod3 ? opcode_timings_p6_f7_mod3 : opcode_timings_p6_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - ins_table = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + ins_table = mod3 ? opcode_timings_p6_ff_mod3 : opcode_timings_p6_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - ins_table = mod3 ? opcode_timings_mod3 : opcode_timings; + ins_table = mod3 ? opcode_timings_p6_mod3 : opcode_timings_p6; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c index 3951acc942..aa78ee1c96 100644 --- a/src/cpu/codegen_timing_pentium.c +++ b/src/cpu/codegen_timing_pentium.c @@ -21,6 +21,7 @@ #include "x86.h" #include "x86_ops.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_ops.h" @@ -109,7 +110,7 @@ static uint32_t addr_regmask; static int fpu_latency; static int fpu_st_latency[8]; -static uint64_t opcode_timings[256] = { +static uint64_t opcode_timings_p6[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RM, PAIR_UV | CYCLES_RM, @@ -246,7 +247,7 @@ static uint64_t opcode_timings[256] = { // clang-format on }; -static uint64_t opcode_timings_mod3[256] = { +static uint64_t opcode_timings_p6_mod3[256] = { // clang-format off /* ADD ADD ADD ADD*/ /*00*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, @@ -384,7 +385,7 @@ static uint64_t opcode_timings_mod3[256] = { // clang-format on }; -static uint64_t opcode_timings_0f[256] = { +static uint64_t opcode_timings_p6_0f[256] = { // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -467,7 +468,7 @@ static uint64_t opcode_timings_0f[256] = { PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, PAIR_U | CYCLES_RM, INVALID, // clang-format on }; -static uint64_t opcode_timings_0f_mod3[256] = { +static uint64_t opcode_timings_p6_0f_mod3[256] = { // clang-format off /*00*/ PAIR_NP | CYCLES(20), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(10), INVALID, PAIR_NP | CYCLES(195), PAIR_NP | CYCLES(7), INVALID, @@ -551,20 +552,20 @@ static uint64_t opcode_timings_0f_mod3[256] = { // clang-format on }; -static uint64_t opcode_timings_shift[8] = { +static uint64_t opcode_timings_p6_shift[8] = { // clang-format off PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, PAIR_U | CYCLES_RMW, // clang-format on }; -static uint64_t opcode_timings_shift_mod3[8] = { +static uint64_t opcode_timings_p6_shift_mod3[8] = { // clang-format off PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, PAIR_U | CYCLES_REG, // clang-format on }; -static uint64_t opcode_timings_f6[8] = { +static uint64_t opcode_timings_p6_f6[8] = { // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), @@ -572,7 +573,7 @@ static uint64_t opcode_timings_f6[8] = { PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) // clang-format on }; -static uint64_t opcode_timings_f6_mod3[8] = { +static uint64_t opcode_timings_p6_f6_mod3[8] = { // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), @@ -580,7 +581,7 @@ static uint64_t opcode_timings_f6_mod3[8] = { PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(11), PAIR_NP | CYCLES(17), PAIR_NP | CYCLES(22) // clang-format on }; -static uint64_t opcode_timings_f7[8] = { +static uint64_t opcode_timings_p6_f7[8] = { // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_RM, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), @@ -588,7 +589,7 @@ static uint64_t opcode_timings_f7[8] = { PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) // clang-format on }; -static uint64_t opcode_timings_f7_mod3[8] = { +static uint64_t opcode_timings_p6_f7_mod3[8] = { // clang-format off /* TST NOT NEG*/ PAIR_UV | CYCLES_REG, INVALID, PAIR_NP | CYCLES(3), PAIR_NP | CYCLES(3), @@ -596,7 +597,7 @@ static uint64_t opcode_timings_f7_mod3[8] = { PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(11,10), PAIR_NP | CYCLES_MULTI(25,41), PAIR_NP | CYCLES_MULTI(30,46) // clang-format on }; -static uint64_t opcode_timings_ff[8] = { +static uint64_t opcode_timings_p6_ff[8] = { // clang-format off /* INC DEC CALL CALL far*/ PAIR_UV | CYCLES_RMW, PAIR_UV | CYCLES_RMW, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), @@ -604,7 +605,7 @@ static uint64_t opcode_timings_ff[8] = { PAIR_NP | CYCLES(2), PAIR_NP | CYCLES(0), PAIR_NP | CYCLES(2), INVALID // clang-format on }; -static uint64_t opcode_timings_ff_mod3[8] = { +static uint64_t opcode_timings_p6_ff_mod3[8] = { // clang-format off /* INC DEC CALL CALL far*/ PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_NP | CYCLES(4), PAIR_NP | CYCLES(0), @@ -613,7 +614,7 @@ static uint64_t opcode_timings_ff_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_d8[8] = { +static uint64_t opcode_timings_p6_d8[8] = { // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -621,7 +622,7 @@ static uint64_t opcode_timings_d8[8] = { PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) // clang-format on }; -static uint64_t opcode_timings_d8_mod3[8] = { +static uint64_t opcode_timings_p6_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -630,7 +631,7 @@ static uint64_t opcode_timings_d8_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_d9[8] = { +static uint64_t opcode_timings_p6_d9[8] = { // clang-format off /* FLDs FSTs FSTPs*/ PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), @@ -638,7 +639,7 @@ static uint64_t opcode_timings_d9[8] = { PAIR_NP | FPU_CYCLES(32,0,0), PAIR_NP | FPU_CYCLES(8,0,0), PAIR_NP | FPU_CYCLES(48,0,0), PAIR_NP | FPU_CYCLES(2,0,0) // clang-format on }; -static uint64_t opcode_timings_d9_mod3[64] = { +static uint64_t opcode_timings_p6_d9_mod3[64] = { // clang-format off /*FLD*/ PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -671,7 +672,7 @@ static uint64_t opcode_timings_d9_mod3[64] = { // clang-format on }; -static uint64_t opcode_timings_da[8] = { +static uint64_t opcode_timings_p6_da[8] = { // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), @@ -679,7 +680,7 @@ static uint64_t opcode_timings_da[8] = { PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) // clang-format on }; -static uint64_t opcode_timings_da_mod3[8] = { +static uint64_t opcode_timings_p6_da_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ @@ -687,7 +688,7 @@ static uint64_t opcode_timings_da_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_db[8] = { +static uint64_t opcode_timings_p6_db[8] = { // clang-format off /* FLDil FSTil FSTPil*/ PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), @@ -695,7 +696,7 @@ static uint64_t opcode_timings_db[8] = { INVALID, PAIR_NP | FPU_CYCLES(3,0,0), INVALID, PAIR_NP | FPU_CYCLES(3,0,0) // clang-format on }; -static uint64_t opcode_timings_db_mod3[64] = { +static uint64_t opcode_timings_p6_db_mod3[64] = { // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -725,7 +726,7 @@ static uint64_t opcode_timings_db_mod3[64] = { // clang-format on }; -static uint64_t opcode_timings_dc[8] = { +static uint64_t opcode_timings_p6_dc[8] = { // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(1,0,0), PAIR_FX | FPU_CYCLES(1,0,0), @@ -733,7 +734,7 @@ static uint64_t opcode_timings_dc[8] = { PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(39,38,2), PAIR_FX | FPU_CYCLES(39,38,2) // clang-format on }; -static uint64_t opcode_timings_dc_mod3[8] = { +static uint64_t opcode_timings_p6_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, INVALID, @@ -742,7 +743,7 @@ static uint64_t opcode_timings_dc_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_dd[8] = { +static uint64_t opcode_timings_p6_dd[8] = { // clang-format off /* FLDd FSTd FSTPd*/ PAIR_FX | FPU_CYCLES(1,0,0), INVALID, PAIR_NP | FPU_CYCLES(2,0,0), PAIR_NP | FPU_CYCLES(2,0,0), @@ -750,7 +751,7 @@ static uint64_t opcode_timings_dd[8] = { PAIR_NP | FPU_CYCLES(70,0,0), INVALID, PAIR_NP | FPU_CYCLES(127,0,0), PAIR_NP | FPU_CYCLES(6,0,0) // clang-format on }; -static uint64_t opcode_timings_dd_mod3[8] = { +static uint64_t opcode_timings_p6_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP*/ PAIR_NP | FPU_CYCLES(2,0,0), INVALID, PAIR_NP | FPU_CYCLES(1,0,0), PAIR_NP | FPU_CYCLES(1,0,0), @@ -759,7 +760,7 @@ static uint64_t opcode_timings_dd_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_de[8] = { +static uint64_t opcode_timings_p6_de[8] = { // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(4,0,0), PAIR_NP | FPU_CYCLES(4,0,0), @@ -767,7 +768,7 @@ static uint64_t opcode_timings_de[8] = { PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(6,2,2), PAIR_NP | FPU_CYCLES(42,38,2), PAIR_NP | FPU_CYCLES(42,38,2) // clang-format on }; -static uint64_t opcode_timings_de_mod3[8] = { +static uint64_t opcode_timings_p6_de_mod3[8] = { // clang-format off /* FADDP FMULP FCOMPP*/ PAIR_FX | FPU_CYCLES(3,2,2), PAIR_FX | FPU_CYCLES(3,2,2), INVALID, PAIR_FX | FPU_CYCLES(1,0,0), @@ -776,7 +777,7 @@ static uint64_t opcode_timings_de_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_df[8] = { +static uint64_t opcode_timings_p6_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw*/ PAIR_NP | FPU_CYCLES(3,2,2), INVALID, PAIR_NP | FPU_CYCLES(6,0,0), PAIR_NP | FPU_CYCLES(6,0,0), @@ -784,7 +785,7 @@ static uint64_t opcode_timings_df[8] = { INVALID, PAIR_NP | FPU_CYCLES(3,2,2), PAIR_NP | FPU_CYCLES(148,0,0), PAIR_NP | FPU_CYCLES(6,0,0) // clang-format on }; -static uint64_t opcode_timings_df_mod3[8] = { +static uint64_t opcode_timings_p6_df_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ @@ -792,25 +793,25 @@ static uint64_t opcode_timings_df_mod3[8] = { // clang-format on }; -static uint64_t opcode_timings_81[8] = { +static uint64_t opcode_timings_p6_81[8] = { // clang-format off PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RMW | CYCLES_IMM1632, PAIR_UV | CYCLES_RM | CYCLES_IMM1632 // clang-format on }; -static uint64_t opcode_timings_81_mod3[8] = { +static uint64_t opcode_timings_p6_81_mod3[8] = { // clang-format off PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG // clang-format on }; -static uint64_t opcode_timings_8x[8] = { +static uint64_t opcode_timings_p6_8x[8] = { // clang-format off PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RMW | CYCLES_IMM8, PAIR_UV | CYCLES_RM | CYCLES_IMM8 // clang-format on }; -static uint64_t opcode_timings_8x_mod3[8] = { +static uint64_t opcode_timings_p6_8x_mod3[8] = { // clang-format off PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG, PAIR_UV | CYCLES_REG @@ -1096,47 +1097,47 @@ codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUS switch (last_prefix) { case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + timings = mod3 ? opcode_timings_p6_0f_mod3 : opcode_timings_p6_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + timings = mod3 ? opcode_timings_p6_d8_mod3 : opcode_timings_p6_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + timings = mod3 ? opcode_timings_p6_d9_mod3 : opcode_timings_p6_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + timings = mod3 ? opcode_timings_p6_da_mod3 : opcode_timings_p6_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + timings = mod3 ? opcode_timings_p6_db_mod3 : opcode_timings_p6_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + timings = mod3 ? opcode_timings_p6_dc_mod3 : opcode_timings_p6_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + timings = mod3 ? opcode_timings_p6_dd_mod3 : opcode_timings_p6_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + timings = mod3 ? opcode_timings_p6_de_mod3 : opcode_timings_p6_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + timings = mod3 ? opcode_timings_p6_df_mod3 : opcode_timings_p6_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -1146,12 +1147,12 @@ codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUS case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + timings = mod3 ? opcode_timings_p6_8x_mod3 : opcode_timings_p6_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + timings = mod3 ? opcode_timings_p6_81_mod3 : opcode_timings_p6_81; deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; opcode = (fetchdat >> 3) & 7; break; @@ -1160,36 +1161,36 @@ codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUS case 0xc1: case 0xd0: case 0xd1: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + timings = mod3 ? opcode_timings_p6_shift_mod3 : opcode_timings_p6_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + timings = mod3 ? opcode_timings_p6_shift_mod3 : opcode_timings_p6_shift; deps = mod3 ? opcode_deps_shift_cl_mod3 : opcode_deps_shift_cl; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + timings = mod3 ? opcode_timings_p6_f6_mod3 : opcode_timings_p6_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + timings = mod3 ? opcode_timings_p6_f7_mod3 : opcode_timings_p6_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + timings = mod3 ? opcode_timings_p6_ff_mod3 : opcode_timings_p6_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; + timings = mod3 ? opcode_timings_p6_mod3 : opcode_timings_p6; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c index 11dd912b4f..3597517cef 100644 --- a/src/cpu/codegen_timing_winchip.c +++ b/src/cpu/codegen_timing_winchip.c @@ -9,6 +9,7 @@ #include "x86.h" #include "x86_ops.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_ops.h" @@ -17,7 +18,7 @@ #define CYCLES(c) (int *) c #define CYCLES2(c16, c32) (int *) ((-1 & ~0xffff) | c16 | (c32 << 8)) -static int *opcode_timings[256] = { +static int *opcode_timings_winchip[256] = { // clang-format off /*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), @@ -41,7 +42,7 @@ static int *opcode_timings[256] = { // clang-format on }; -static int *opcode_timings_mod3[256] = { +static int *opcode_timings_winchip_mod3[256] = { // clang-format off /*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL, /*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), @@ -65,7 +66,7 @@ static int *opcode_timings_mod3[256] = { // clang-format on }; -static int *opcode_timings_0f[256] = { +static int *opcode_timings_winchip_0f[256] = { // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -88,7 +89,7 @@ static int *opcode_timings_0f[256] = { /*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, // clang-format on }; -static int *opcode_timings_0f_mod3[256] = { +static int *opcode_timings_winchip_0f_mod3[256] = { // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL, /*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -112,68 +113,68 @@ static int *opcode_timings_0f_mod3[256] = { // clang-format on }; -static int *opcode_timings_shift[8] = { +static int *opcode_timings_winchip_shift[8] = { // clang-format off CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) // clang-format on }; -static int *opcode_timings_shift_mod3[8] = { +static int *opcode_timings_winchip_shift_mod3[8] = { // clang-format off CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) // clang-format on }; -static int *opcode_timings_f6[8] = { +static int *opcode_timings_winchip_f6[8] = { // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) // clang-format on }; -static int *opcode_timings_f6_mod3[8] = { +static int *opcode_timings_winchip_f6_mod3[8] = { // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) // clang-format on }; -static int *opcode_timings_f7[8] = { +static int *opcode_timings_winchip_f7[8] = { // clang-format off &timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) // clang-format on }; -static int *opcode_timings_f7_mod3[8] = { +static int *opcode_timings_winchip_f7_mod3[8] = { // clang-format off &timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) // clang-format on }; -static int *opcode_timings_ff[8] = { +static int *opcode_timings_winchip_ff[8] = { // clang-format off &timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL // clang-format on }; -static int *opcode_timings_ff_mod3[8] = { +static int *opcode_timings_winchip_ff_mod3[8] = { // clang-format off &timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL // clang-format on }; -static int *opcode_timings_d8[8] = { +static int *opcode_timings_winchip_d8[8] = { // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78) // clang-format on }; -static int *opcode_timings_d8_mod3[8] = { +static int *opcode_timings_winchip_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/ CYCLES(4), CYCLES(6), CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72) // clang-format on }; -static int *opcode_timings_d9[8] = { +static int *opcode_timings_winchip_d9[8] = { // clang-format off /* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/ CYCLES(2), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3) // clang-format on }; -static int *opcode_timings_d9_mod3[64] = { +static int *opcode_timings_winchip_d9_mod3[64] = { // clang-format off /*FLD*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), @@ -194,25 +195,25 @@ static int *opcode_timings_d9_mod3[64] = { // clang-format on }; -static int *opcode_timings_da[8] = { +static int *opcode_timings_winchip_da[8] = { // clang-format off /* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78) // clang-format on }; -static int *opcode_timings_da_mod3[8] = { +static int *opcode_timings_winchip_da_mod3[8] = { // clang-format off NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL // clang-format on }; -static int *opcode_timings_db[8] = { +static int *opcode_timings_winchip_db[8] = { // clang-format off /* FLDil FSTil FSTPil FLDe FSTPe*/ CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), NULL, CYCLES(8) // clang-format on }; -static int *opcode_timings_db_mod3[64] = { +static int *opcode_timings_winchip_db_mod3[64] = { // clang-format off NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -226,71 +227,71 @@ static int *opcode_timings_db_mod3[64] = { // clang-format on }; -static int *opcode_timings_dc[8] = { +static int *opcode_timings_winchip_dc[8] = { // clang-format off /* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/ CYCLES(6), CYCLES(8), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(74), CYCLES(74) // clang-format on }; -static int *opcode_timings_dc_mod3[8] = { +static int *opcode_timings_winchip_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/ CYCLES(4), CYCLES(6), NULL, NULL, CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72) // clang-format on }; -static int *opcode_timings_dd[8] = { +static int *opcode_timings_winchip_dd[8] = { // clang-format off /* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/ CYCLES(2), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(5) // clang-format on }; -static int *opcode_timings_dd_mod3[8] = { +static int *opcode_timings_winchip_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL // clang-format on }; -static int *opcode_timings_de[8] = { +static int *opcode_timings_winchip_de[8] = { // clang-format off /* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/ CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78) // clang-format on }; -static int *opcode_timings_de_mod3[8] = { +static int *opcode_timings_winchip_de_mod3[8] = { // clang-format off /* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/ CYCLES(4), CYCLES(6), NULL, CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72) // clang-format on }; -static int *opcode_timings_df[8] = { +static int *opcode_timings_winchip_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/ CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), CYCLES(172), CYCLES(8) // clang-format on }; -static int *opcode_timings_df_mod3[8] = { +static int *opcode_timings_winchip_df_mod3[8] = { // clang-format off /* FFREE FST FSTP FUCOM FUCOMP*/ CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL // clang-format on }; -static int *opcode_timings_8x[8] = { +static int *opcode_timings_winchip_8x[8] = { // clang-format off &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm }; -static int *opcode_timings_8x_mod3[8] = +static int *opcode_timings_winchip_8x_mod3[8] = { &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm }; -static int *opcode_timings_81[8] = +static int *opcode_timings_winchip_81[8] = { &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm }; -static int *opcode_timings_81_mod3[8] = +static int *opcode_timings_winchip_81_mod3[8] = { &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm // clang-format on @@ -329,7 +330,7 @@ codegen_timing_winchip_start(void) void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat) { - timing_count += COUNT(opcode_timings[prefix], 0); + timing_count += COUNT(opcode_timings_winchip[prefix], 0); last_prefix = prefix; } @@ -343,47 +344,47 @@ codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUS switch (last_prefix) { case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + timings = mod3 ? opcode_timings_winchip_0f_mod3 : opcode_timings_winchip_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + timings = mod3 ? opcode_timings_winchip_d8_mod3 : opcode_timings_winchip_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + timings = mod3 ? opcode_timings_winchip_d9_mod3 : opcode_timings_winchip_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + timings = mod3 ? opcode_timings_winchip_da_mod3 : opcode_timings_winchip_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + timings = mod3 ? opcode_timings_winchip_db_mod3 : opcode_timings_winchip_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + timings = mod3 ? opcode_timings_winchip_dc_mod3 : opcode_timings_winchip_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + timings = mod3 ? opcode_timings_winchip_dd_mod3 : opcode_timings_winchip_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + timings = mod3 ? opcode_timings_winchip_de_mod3 : opcode_timings_winchip_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + timings = mod3 ? opcode_timings_winchip_df_mod3 : opcode_timings_winchip_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -393,12 +394,12 @@ codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUS case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + timings = mod3 ? opcode_timings_winchip_8x_mod3 : opcode_timings_winchip_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + timings = mod3 ? opcode_timings_winchip_81_mod3 : opcode_timings_winchip_81; deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; opcode = (fetchdat >> 3) & 7; break; @@ -409,29 +410,29 @@ codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNUS case 0xd1: case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + timings = mod3 ? opcode_timings_winchip_shift_mod3 : opcode_timings_winchip_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + timings = mod3 ? opcode_timings_winchip_f6_mod3 : opcode_timings_winchip_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + timings = mod3 ? opcode_timings_winchip_f7_mod3 : opcode_timings_winchip_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + timings = mod3 ? opcode_timings_winchip_ff_mod3 : opcode_timings_winchip_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; + timings = mod3 ? opcode_timings_winchip_mod3 : opcode_timings_winchip; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } diff --git a/src/cpu/codegen_timing_winchip2.c b/src/cpu/codegen_timing_winchip2.c index d4e32611e4..f37fe33660 100644 --- a/src/cpu/codegen_timing_winchip2.c +++ b/src/cpu/codegen_timing_winchip2.c @@ -18,6 +18,7 @@ #include "x86.h" #include "x86_ops.h" +#include "x87_sf.h" #include "x87.h" #include "codegen.h" #include "codegen_ops.h" @@ -62,7 +63,7 @@ #define INVALID 0 -static uint32_t opcode_timings[256] = { +static uint32_t opcode_timings_winchip2[256] = { // clang-format off /*00*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), INVALID, /*10*/ CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), @@ -86,7 +87,7 @@ static uint32_t opcode_timings[256] = { // clang-format on }; -static uint32_t opcode_timings_mod3[256] = { +static uint32_t opcode_timings_winchip2_mod3[256] = { // clang-format off /*00*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), INVALID, /*10*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(3), @@ -110,7 +111,7 @@ static uint32_t opcode_timings_mod3[256] = { // clang-format on }; -static uint32_t opcode_timings_0f[256] = { +static uint32_t opcode_timings_winchip2_0f[256] = { // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1), /*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -133,7 +134,7 @@ static uint32_t opcode_timings_0f[256] = { /*f0*/ INVALID, CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), CYCLES_MMX_SHIFT(2), INVALID, CYCLES_MMX_MUL(2), INVALID, INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), CYCLES_MMX_ANY(2), INVALID, // clang-format on }; -static uint32_t opcode_timings_0f_mod3[256] = { +static uint32_t opcode_timings_winchip2_0f_mod3[256] = { // clang-format off /*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), INVALID, CYCLES(195), CYCLES(7), INVALID, CYCLES(1000), CYCLES(10000), INVALID, INVALID, INVALID, CYCLES_3DNOW(1), CYCLES(1), CYCLES_3DNOW(1), /*10*/ INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -157,49 +158,49 @@ static uint32_t opcode_timings_0f_mod3[256] = { // clang-format on }; -static uint32_t opcode_timings_shift[8] = { +static uint32_t opcode_timings_winchip2_shift[8] = { // clang-format off CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7) // clang-format on }; -static uint32_t opcode_timings_shift_mod3[8] = { +static uint32_t opcode_timings_winchip2_shift_mod3[8] = { // clang-format off CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3) // clang-format on }; -static uint32_t opcode_timings_f6[8] = { +static uint32_t opcode_timings_winchip2_f6[8] = { // clang-format off CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) // clang-format on }; -static uint32_t opcode_timings_f6_mod3[8] = { +static uint32_t opcode_timings_winchip2_f6_mod3[8] = { // clang-format off CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19) // clang-format on }; -static uint32_t opcode_timings_f7[8] = { +static uint32_t opcode_timings_winchip2_f7[8] = { // clang-format off CYCLES(2), INVALID, CYCLES(2), CYCLES(2), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) // clang-format on }; -static uint32_t opcode_timings_f7_mod3[8] = { +static uint32_t opcode_timings_winchip2_f7_mod3[8] = { // clang-format off CYCLES(1), INVALID, CYCLES(1), CYCLES(1), CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43) // clang-format on }; -static uint32_t opcode_timings_ff[8] = { +static uint32_t opcode_timings_winchip2_ff[8] = { // clang-format off CYCLES(2), CYCLES(2), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID // clang-format on }; -static uint32_t opcode_timings_ff_mod3[8] = { +static uint32_t opcode_timings_winchip2_ff_mod3[8] = { // clang-format off CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), INVALID // clang-format on }; -static uint32_t opcode_timings_d8[8] = { +static uint32_t opcode_timings_winchip2_d8[8] = { // clang-format off /* FADDs FMULs FCOMs FCOMPs*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), @@ -207,7 +208,7 @@ static uint32_t opcode_timings_d8[8] = { FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) // clang-format on }; -static uint32_t opcode_timings_d8_mod3[8] = { +static uint32_t opcode_timings_winchip2_d8_mod3[8] = { // clang-format off /* FADD FMUL FCOM FCOMP*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), @@ -216,7 +217,7 @@ static uint32_t opcode_timings_d8_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_d9[8] = { +static uint32_t opcode_timings_winchip2_d9[8] = { // clang-format off /* FLDs FSTs FSTPs*/ FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), @@ -224,7 +225,7 @@ static uint32_t opcode_timings_d9[8] = { FPU_CYCLES(32,0,0), FPU_CYCLES(8,0,0), FPU_CYCLES(48,0,0), FPU_CYCLES(2,0,0) // clang-format on }; -static uint32_t opcode_timings_d9_mod3[64] = { +static uint32_t opcode_timings_winchip2_d9_mod3[64] = { // clang-format off /*FLD*/ FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), @@ -257,7 +258,7 @@ static uint32_t opcode_timings_d9_mod3[64] = { // clang-format on }; -static uint32_t opcode_timings_da[8] = { +static uint32_t opcode_timings_winchip2_da[8] = { // clang-format off /* FIADDl FIMULl FICOMl FICOMPl*/ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0), @@ -265,7 +266,7 @@ static uint32_t opcode_timings_da[8] = { FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2) // clang-format on }; -static uint32_t opcode_timings_da_mod3[8] = { +static uint32_t opcode_timings_winchip2_da_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FCOMPP*/ @@ -273,7 +274,7 @@ static uint32_t opcode_timings_da_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_db[8] = { +static uint32_t opcode_timings_winchip2_db[8] = { // clang-format off /* FLDil FSTil FSTPil*/ FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0), @@ -281,7 +282,7 @@ static uint32_t opcode_timings_db[8] = { INVALID, FPU_CYCLES(3,0,0), INVALID, FPU_CYCLES(3,0,0) // clang-format on }; -static uint32_t opcode_timings_db_mod3[64] = { +static uint32_t opcode_timings_winchip2_db_mod3[64] = { // clang-format off INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, @@ -311,7 +312,7 @@ static uint32_t opcode_timings_db_mod3[64] = { // clang-format on }; -static uint32_t opcode_timings_dc[8] = { +static uint32_t opcode_timings_winchip2_dc[8] = { // clang-format off /* FADDd FMULd FCOMd FCOMPd*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), @@ -319,7 +320,7 @@ static uint32_t opcode_timings_dc[8] = { FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), FPU_CYCLES(39,38,2), FPU_CYCLES(39,38,2) // clang-format on }; -static uint32_t opcode_timings_dc_mod3[8] = { +static uint32_t opcode_timings_winchip2_dc_mod3[8] = { // clang-format off /* opFADDr opFMULr*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2),INVALID, INVALID, @@ -328,7 +329,7 @@ static uint32_t opcode_timings_dc_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_dd[8] = { +static uint32_t opcode_timings_winchip2_dd[8] = { // clang-format off /* FLDd FSTd FSTPd*/ FPU_CYCLES(1,0,0), INVALID, FPU_CYCLES(2,0,0), FPU_CYCLES(2,0,0), @@ -336,7 +337,7 @@ static uint32_t opcode_timings_dd[8] = { FPU_CYCLES(70,0,0), INVALID, FPU_CYCLES(127,0,0), FPU_CYCLES(6,0,0) // clang-format on }; -static uint32_t opcode_timings_dd_mod3[8] = { +static uint32_t opcode_timings_winchip2_dd_mod3[8] = { // clang-format off /* FFFREE FST FSTP*/ FPU_CYCLES(2,0,0), INVALID, FPU_CYCLES(1,0,0), FPU_CYCLES(1,0,0), @@ -345,7 +346,7 @@ static uint32_t opcode_timings_dd_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_de[8] = { +static uint32_t opcode_timings_winchip2_de[8] = { // clang-format off /* FIADDw FIMULw FICOMw FICOMPw*/ FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(4,0,0), FPU_CYCLES(4,0,0), @@ -353,7 +354,7 @@ static uint32_t opcode_timings_de[8] = { FPU_CYCLES(6,2,2), FPU_CYCLES(6,2,2), FPU_CYCLES(42,38,2), FPU_CYCLES(42,38,2) // clang-format on }; -static uint32_t opcode_timings_de_mod3[8] = { +static uint32_t opcode_timings_winchip2_de_mod3[8] = { // clang-format off /* FADDP FMULP FCOMPP*/ FPU_CYCLES(3,2,2), FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(1,0,0), @@ -362,7 +363,7 @@ static uint32_t opcode_timings_de_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_df[8] = { +static uint32_t opcode_timings_winchip2_df[8] = { // clang-format off /* FILDiw FISTiw FISTPiw*/ FPU_CYCLES(3,2,2), INVALID, FPU_CYCLES(6,0,0), FPU_CYCLES(6,0,0), @@ -370,7 +371,7 @@ static uint32_t opcode_timings_df[8] = { INVALID, FPU_CYCLES(3,2,2), FPU_CYCLES(148,0,0), FPU_CYCLES(6,0,0) // clang-format on }; -static uint32_t opcode_timings_df_mod3[8] = { +static uint32_t opcode_timings_winchip2_df_mod3[8] = { // clang-format off INVALID, INVALID, INVALID, INVALID, /* FSTSW AX*/ @@ -378,22 +379,22 @@ static uint32_t opcode_timings_df_mod3[8] = { // clang-format on }; -static uint32_t opcode_timings_8x[8] = { +static uint32_t opcode_timings_winchip2_8x[8] = { // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) // clang-format on }; -static uint32_t opcode_timings_8x_mod3[8] = { +static uint32_t opcode_timings_winchip2_8x_mod3[8] = { // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) // clang-format on }; -static uint32_t opcode_timings_81[8] = { +static uint32_t opcode_timings_winchip2_81[8] = { // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) // clang-format on }; -static uint32_t opcode_timings_81_mod3[8] = { +static uint32_t opcode_timings_winchip2_81_mod3[8] = { // clang-format off CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(2) // clang-format on @@ -612,47 +613,47 @@ codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNU switch (last_prefix) { case 0x0f: - timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f; + timings = mod3 ? opcode_timings_winchip2_0f_mod3 : opcode_timings_winchip2_0f; deps = mod3 ? opcode_deps_0f_mod3 : opcode_deps_0f; break; case 0xd8: - timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8; + timings = mod3 ? opcode_timings_winchip2_d8_mod3 : opcode_timings_winchip2_d8; deps = mod3 ? opcode_deps_d8_mod3 : opcode_deps_d8; opcode = (opcode >> 3) & 7; break; case 0xd9: - timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9; + timings = mod3 ? opcode_timings_winchip2_d9_mod3 : opcode_timings_winchip2_d9; deps = mod3 ? opcode_deps_d9_mod3 : opcode_deps_d9; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xda: - timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da; + timings = mod3 ? opcode_timings_winchip2_da_mod3 : opcode_timings_winchip2_da; deps = mod3 ? opcode_deps_da_mod3 : opcode_deps_da; opcode = (opcode >> 3) & 7; break; case 0xdb: - timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db; + timings = mod3 ? opcode_timings_winchip2_db_mod3 : opcode_timings_winchip2_db; deps = mod3 ? opcode_deps_db_mod3 : opcode_deps_db; opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7; break; case 0xdc: - timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc; + timings = mod3 ? opcode_timings_winchip2_dc_mod3 : opcode_timings_winchip2_dc; deps = mod3 ? opcode_deps_dc_mod3 : opcode_deps_dc; opcode = (opcode >> 3) & 7; break; case 0xdd: - timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd; + timings = mod3 ? opcode_timings_winchip2_dd_mod3 : opcode_timings_winchip2_dd; deps = mod3 ? opcode_deps_dd_mod3 : opcode_deps_dd; opcode = (opcode >> 3) & 7; break; case 0xde: - timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de; + timings = mod3 ? opcode_timings_winchip2_de_mod3 : opcode_timings_winchip2_de; deps = mod3 ? opcode_deps_de_mod3 : opcode_deps_de; opcode = (opcode >> 3) & 7; break; case 0xdf: - timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df; + timings = mod3 ? opcode_timings_winchip2_df_mod3 : opcode_timings_winchip2_df; deps = mod3 ? opcode_deps_df_mod3 : opcode_deps_df; opcode = (opcode >> 3) & 7; break; @@ -662,12 +663,12 @@ codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNU case 0x80: case 0x82: case 0x83: - timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; + timings = mod3 ? opcode_timings_winchip2_8x_mod3 : opcode_timings_winchip2_8x; deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: - timings = mod3 ? opcode_timings_81_mod3 : opcode_timings_81; + timings = mod3 ? opcode_timings_winchip2_81_mod3 : opcode_timings_winchip2_81; deps = mod3 ? opcode_deps_81_mod3 : opcode_deps_81; opcode = (fetchdat >> 3) & 7; break; @@ -678,29 +679,29 @@ codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, UNU case 0xd1: case 0xd2: case 0xd3: - timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift; + timings = mod3 ? opcode_timings_winchip2_shift_mod3 : opcode_timings_winchip2_shift; deps = mod3 ? opcode_deps_shift_mod3 : opcode_deps_shift; opcode = (fetchdat >> 3) & 7; break; case 0xf6: - timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6; + timings = mod3 ? opcode_timings_winchip2_f6_mod3 : opcode_timings_winchip2_f6; deps = mod3 ? opcode_deps_f6_mod3 : opcode_deps_f6; opcode = (fetchdat >> 3) & 7; break; case 0xf7: - timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7; + timings = mod3 ? opcode_timings_winchip2_f7_mod3 : opcode_timings_winchip2_f7; deps = mod3 ? opcode_deps_f7_mod3 : opcode_deps_f7; opcode = (fetchdat >> 3) & 7; break; case 0xff: - timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff; + timings = mod3 ? opcode_timings_winchip2_ff_mod3 : opcode_timings_winchip2_ff; deps = mod3 ? opcode_deps_ff_mod3 : opcode_deps_ff; opcode = (fetchdat >> 3) & 7; break; default: - timings = mod3 ? opcode_timings_mod3 : opcode_timings; + timings = mod3 ? opcode_timings_winchip2_mod3 : opcode_timings_winchip2; deps = mod3 ? opcode_deps_mod3 : opcode_deps; break; } diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b812a24f94..0c6d360976 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -29,6 +29,8 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include "cpu.h" +#include "x86.h" +#include "x87_sf.h" #include <86box/device.h> #include <86box/machine.h> #include <86box/io.h> @@ -38,13 +40,14 @@ #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> #ifdef USE_DYNAREC # include "codegen.h" -#endif +#endif /* USE_DYNAREC */ #include "x87_timings.h" #define CCR1_USE_SMI (1 << 1) @@ -116,7 +119,7 @@ const OpFn *x86_dynarec_opcodes_df_a32; const OpFn *x86_dynarec_opcodes_REPE; const OpFn *x86_dynarec_opcodes_REPNE; const OpFn *x86_dynarec_opcodes_3DNOW; -#endif +#endif /* USE_DYNAREC */ const OpFn *x86_opcodes; const OpFn *x86_opcodes_0f; @@ -179,6 +182,8 @@ int cpu_rom_prefetch_cycles; int cpu_waitstates; int cpu_cache_int_enabled; int cpu_cache_ext_enabled; +int cpu_flush_pending; +int cpu_old_paging; int cpu_isa_speed; int cpu_pci_speed; int cpu_isa_pci_div; @@ -501,9 +506,10 @@ cpu_set(void) #ifdef USE_ACYCS acycs = 0; -#endif +#endif /* USE_ACYCS */ - soft_reset_pci = 0; + soft_reset_pci = 0; + cpu_init = 0; cpu_alt_reset = 0; unmask_a20_in_smm = 0; @@ -572,7 +578,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); #else x86_setopcodes(ops_386, ops_386_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_386, ops_2386_386_0f); x86_opcodes_REPE = ops_REPE; x86_opcodes_REPNE = ops_REPNE; @@ -583,7 +589,7 @@ cpu_set(void) x86_dynarec_opcodes_REPE = dynarec_ops_REPE; x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW; -#endif +#endif /* USE_DYNAREC */ if (hasfpu) { #ifdef USE_DYNAREC @@ -622,7 +628,7 @@ cpu_set(void) x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; } -#endif +#endif /* USE_DYNAREC */ if (fpu_softfloat) { x86_opcodes_d8_a16 = ops_sf_fpu_d8_a16; x86_opcodes_d8_a32 = ops_sf_fpu_d8_a32; @@ -710,7 +716,7 @@ cpu_set(void) x86_dynarec_opcodes_de_a32 = dynarec_ops_nofpu_a32; x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32; -#endif +#endif /* USE_DYNAREC */ x86_opcodes_d8_a16 = ops_nofpu_a16; x86_opcodes_d8_a32 = ops_nofpu_a32; x86_opcodes_d9_a16 = ops_nofpu_a16; @@ -748,7 +754,7 @@ cpu_set(void) #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_486); -#endif +#endif /* USE_DYNAREC */ memset(&msr, 0, sizeof(msr)); @@ -770,7 +776,7 @@ cpu_set(void) x86_setopcodes(ops_186, ops_186_0f, dynarec_ops_186, dynarec_ops_186_0f); #else x86_setopcodes(ops_186, ops_186_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_186, ops_2386_186_0f); break; @@ -779,7 +785,7 @@ cpu_set(void) x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f); #else x86_setopcodes(ops_286, ops_286_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_286, ops_2386_286_0f); if (fpu_type == FPU_287) { @@ -815,7 +821,7 @@ cpu_set(void) x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; } -#endif +#endif /* USE_DYNAREC */ if (fpu_softfloat) { x86_opcodes_d9_a16 = ops_sf_fpu_287_d9_a16; x86_opcodes_d9_a32 = ops_sf_fpu_287_d9_a32; @@ -917,7 +923,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_ibm486_0f, dynarec_ops_386, dynarec_ops_ibm486_0f); #else x86_setopcodes(ops_386, ops_ibm486_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_386, ops_2386_ibm486_0f); cpu_features = CPU_FEATURE_MSR; fallthrough; @@ -957,7 +963,7 @@ cpu_set(void) x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; } -#endif +#endif /* USE_DYNAREC */ if (fpu_softfloat) { x86_opcodes_d9_a16 = ops_sf_fpu_287_d9_a16; x86_opcodes_d9_a32 = ops_sf_fpu_287_d9_a32; @@ -1063,7 +1069,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else x86_setopcodes(ops_386, ops_486_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f); timing_rr = 1; /* register dest - register src */ @@ -1103,7 +1109,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else x86_setopcodes(ops_386, ops_486_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f); timing_rr = 1; /* register dest - register src */ @@ -1156,7 +1162,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else x86_setopcodes(ops_386, ops_486_0f); -#endif +#endif /* USE_DYNAREC */ x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f); timing_rr = 1; /* register dest - register src */ @@ -1205,7 +1211,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_stpc_0f); else x86_setopcodes(ops_386, ops_c486_0f); -#endif +#endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ timing_rm = 3; /* register dest - memory src */ @@ -1248,7 +1254,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_c486_0f, dynarec_ops_386, dynarec_ops_c486_0f); #else x86_setopcodes(ops_386, ops_c486_0f); -#endif +#endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ timing_rm = 1; /* register dest - memory src */ @@ -1297,7 +1303,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_winchip2_0f); else x86_setopcodes(ops_386, ops_winchip_0f); -#endif +#endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ timing_rm = 2; /* register dest - memory src */ @@ -1346,7 +1352,7 @@ cpu_set(void) codegen_timing_set(&codegen_timing_winchip2); else codegen_timing_set(&codegen_timing_winchip); -#endif +#endif /* USE_DYNAREC */ break; case CPU_P24T: @@ -1362,7 +1368,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_pentiummmx_0f); else x86_setopcodes(ops_386, ops_pentium_0f); -#endif +#endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ timing_rm = 2; /* register dest - memory src */ @@ -1405,10 +1411,10 @@ cpu_set(void) cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_pentium); -#endif +#endif /* USE_DYNAREC */ break; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -1430,7 +1436,7 @@ cpu_set(void) x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; } -# endif +# endif /* USE_DYNAREC */ if (fpu_softfloat) { x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; x86_opcodes_da_a32 = ops_sf_fpu_686_da_a32; @@ -1468,7 +1474,7 @@ cpu_set(void) # if 0 x86_setopcodes(ops_386, ops_c6x86_0f); # endif -# endif +# endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ timing_rm = 1; /* register dest - memory src */ @@ -1520,19 +1526,65 @@ cpu_set(void) # ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_686); -# endif +# endif /* USE_DYNAREC */ if ((cpu_s->cpu_type == CPU_Cx6x86L) || (cpu_s->cpu_type == CPU_Cx6x86MX)) ccr4 = 0x80; else if (CPU_Cx6x86) CPUID = 0; /* Disabled on powerup by default */ break; -#endif +#endif /* USE_CYRIX_6X86 */ -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) +#ifdef USE_AMD_K5 case CPU_K5: case CPU_5K86: -#endif +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); +#else + x86_setopcodes(ops_386, ops_pentiummmx_0f); +#endif /* USE_DYNAREC */ + + timing_rr = 1; /* register dest - register src */ + timing_rm = 2; /* register dest - memory src */ + timing_mr = 3; /* memory dest - register src */ + timing_mm = 3; + timing_rml = 2; /* register dest - memory src long */ + timing_mrl = 3; /* memory dest - register src long */ + timing_mml = 3; + timing_bt = 0; /* branch taken */ + timing_bnt = 1; /* branch not taken */ + + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /* unknown */ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + + timing_misaligned = 3; + + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PGE; + +#ifdef USE_DYNAREC + codegen_timing_set(&codegen_timing_k5); +#endif /* USE_DYNAREC */ + break; + +#endif /* USE_AMD_K5 */ case CPU_K6: case CPU_K6_2: case CPU_K6_2C: @@ -1542,34 +1594,20 @@ cpu_set(void) #ifdef USE_DYNAREC if (cpu_s->cpu_type >= CPU_K6_2) x86_setopcodes(ops_386, ops_k62_0f, dynarec_ops_386, dynarec_ops_k62_0f); -# if defined(DEV_BRANCH) && defined(USE_AMD_K5) - else if (cpu_s->cpu_type == CPU_K6) - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); - else - x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); -# else else x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); -# endif #else if (cpu_s->cpu_type >= CPU_K6_2) x86_setopcodes(ops_386, ops_k62_0f); -# if defined(DEV_BRANCH) && defined(USE_AMD_K5) - else if (cpu_s->cpu_type == CPU_K6) - x86_setopcodes(ops_386, ops_k6_0f); - else - x86_setopcodes(ops_386, ops_pentiummmx_0f); -# else else x86_setopcodes(ops_386, ops_k6_0f); -# endif -#endif +#endif /* USE_DYNAREC */ if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) { x86_opcodes_3DNOW = ops_3DNOWE; #ifdef USE_DYNAREC x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOWE; -#endif +#endif /* USE_DYNAREC */ } timing_rr = 1; /* register dest - register src */ @@ -1609,27 +1647,15 @@ cpu_set(void) cpu_features |= CPU_FEATURE_3DNOW; if ((cpu_s->cpu_type == CPU_K6_2P) || (cpu_s->cpu_type == CPU_K6_3P)) cpu_features |= CPU_FEATURE_3DNOWE; -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE; - if (cpu_s->cpu_type >= CPU_K6) { - cpu_CR4_mask |= (CR4_VME | CR4_PVI | CR4_PSE); - if (cpu_s->cpu_type <= CPU_K6) - cpu_CR4_mask |= CR4_PCE; - else if (cpu_s->cpu_type >= CPU_K6_2C) - cpu_CR4_mask |= CR4_PGE; - } else - cpu_CR4_mask |= CR4_PGE; -#else cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; if (cpu_s->cpu_type == CPU_K6) cpu_CR4_mask |= CR4_PCE; else if (cpu_s->cpu_type >= CPU_K6_2C) cpu_CR4_mask |= CR4_PGE; -#endif #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_k6); -#endif +#endif /* USE_DYNAREC */ break; case CPU_PENTIUMPRO: @@ -1664,7 +1690,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_pentium2d_0f); else x86_setopcodes(ops_386, ops_pentium2_0f); -#endif +#endif /* USE_DYNAREC */ if (fpu_softfloat) { x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; x86_opcodes_da_a32 = ops_sf_fpu_686_da_a32; @@ -1722,7 +1748,7 @@ cpu_set(void) #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_p6); -#endif +#endif /* USE_DYNAREC */ break; case CPU_CYRIX3S: @@ -1730,7 +1756,7 @@ cpu_set(void) x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); #else x86_setopcodes(ops_386, ops_winchip2_0f); -#endif +#endif /* USE_DYNAREC */ timing_rr = 1; /* register dest - register src */ timing_rm = 2; /* register dest - memory src */ timing_mr = 2; /* memory dest - register src */ @@ -1770,7 +1796,7 @@ cpu_set(void) #ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_winchip); -#endif +#endif /* USE_DYNAREC */ break; default: @@ -1808,7 +1834,7 @@ cpu_set(void) cpu_exec = exec386_dynarec; cpu_use_exec = 1; } else -#endif +#endif /* defined(USE_DYNAREC) && !defined(USE_GDBSTUB) */ /* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */ if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type == CPU_IBM486BL) || cpu_iscyrix || (cpu_s->cpu_type > CPU_486DLC) || cpu_override_interpreter) { @@ -2061,7 +2087,7 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) +#ifdef USE_AMD_K5 case CPU_K5: if (!EAX) { EAX = 0x00000001; @@ -2119,7 +2145,7 @@ cpu_CPUID(void) break; } break; -#endif +#endif /* USE_AMD_K5 */ case CPU_K6: switch (EAX) { @@ -2350,7 +2376,7 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: if (!EAX) { EAX = 0x00000001; @@ -2406,7 +2432,7 @@ cpu_CPUID(void) } else EAX = EBX = ECX = EDX = 0; break; -#endif +#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: if (!EAX) { @@ -2561,10 +2587,10 @@ cpu_ven_reset(void) msr.amd_psor = (cpu_s->cpu_type >= CPU_K6_3) ? 0x008cULL : 0x018cULL; fallthrough; case CPU_K6_2: -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) +#ifdef USE_AMD_K5 case CPU_K5: case CPU_5K86: -#endif +#endif /* USE_AMD_K5 */ case CPU_K6: msr.amd_efer = (cpu_s->cpu_type >= CPU_K6_2C) ? 2ULL : 0ULL; break; @@ -2785,10 +2811,10 @@ cpu_RDMSR(void) } break; -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) +#ifdef USE_AMD_K5 case CPU_K5: case CPU_5K86: -#endif +#endif /* USE_AMD_K5 */ case CPU_K6: case CPU_K6_2: case CPU_K6_2C: @@ -3071,7 +3097,7 @@ cpu_RDMSR(void) cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -3111,7 +3137,7 @@ cpu_RDMSR(void) } cpu_log("RDMSR: ECX = %08X, val = %08X%08X\n", ECX, EDX, EAX); break; -#endif +#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: case CPU_PENTIUM2: @@ -3274,26 +3300,17 @@ cpu_RDMSR(void) break; /* SYSENTER_CS - SYSENTER target CS */ case 0x174: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; - EAX &= 0xffff0000; EAX |= msr.sysenter_cs; EDX = 0x00000000; break; /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; - EAX = msr.sysenter_esp; EDX = 0x00000000; break; /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_rdmsr; - EAX = msr.sysenter_eip; EDX = 0x00000000; break; @@ -3489,7 +3506,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: @@ -3565,7 +3582,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: @@ -3634,10 +3651,10 @@ cpu_WRMSR(void) } break; -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) +#ifdef USE_AMD_K5 case CPU_K5: case CPU_5K86: -#endif +#endif /* USE_AMD_K5 */ case CPU_K6: case CPU_K6_2: case CPU_K6_2C: @@ -3661,7 +3678,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: @@ -3688,7 +3705,7 @@ cpu_WRMSR(void) /* Extended Feature Enable Register */ case 0xc0000080: temp = EAX | ((uint64_t) EDX << 32); - if (temp & ~1ULL) + if (temp & ~0x1fULL) x86gpf(NULL, 0); else msr.amd_efer = temp; @@ -3831,7 +3848,7 @@ cpu_WRMSR(void) /* 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: @@ -3898,7 +3915,7 @@ cpu_WRMSR(void) } break; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -3916,7 +3933,7 @@ cpu_WRMSR(void) 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: @@ -3932,7 +3949,7 @@ cpu_WRMSR(void) break; } break; -#endif +#endif /* USE_CYRIX_6X86 */ case CPU_PENTIUMPRO: case CPU_PENTIUM2: @@ -3949,7 +3966,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; /* Unknown */ case 0x18: @@ -4043,23 +4060,14 @@ cpu_WRMSR(void) break; /* SYSENTER_CS - SYSENTER target CS */ case 0x174: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; - msr.sysenter_cs = EAX & 0xFFFF; break; /* SYSENTER_ESP - SYSENTER target ESP */ case 0x175: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; - msr.sysenter_esp = EAX; break; /* SYSENTER_EIP - SYSENTER target EIP */ case 0x176: - if (cpu_s->cpu_type == CPU_PENTIUMPRO) - goto i686_invalid_wrmsr; - msr.sysenter_eip = EAX; break; /* MCG_CAP - Machine Check Global Capability */ @@ -4245,14 +4253,14 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv)) case 0xe8: /* CCR4 */ if ((ccr3 & 0xf0) == 0x10) { ccr4 = val; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 if (cpu_s->cpu_type >= CPU_Cx6x86) { if (val & 0x80) CPUID = cpu_s->cpuid_model; else CPUID = 0; } -#endif +#endif /* USE_CYRIX_6X86 */ } break; case 0xe9: /* CCR5 */ @@ -4326,7 +4334,7 @@ x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f) x86_opcodes = opcodes; x86_opcodes_0f = opcodes_0f; } -#endif +#endif /* USE_DYNAREC */ void x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f) diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 900d3d7e1b..d96d7951d6 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -21,8 +21,6 @@ #ifndef EMU_CPU_H #define EMU_CPU_H -#include "softfloat/softfloat.h" - enum { FPU_NONE, FPU_8087, @@ -406,22 +404,6 @@ typedef struct { uint32_t _smbase; } cpu_state_t; -typedef struct { - uint16_t cwd; - uint16_t swd; - uint16_t tag; - uint16_t foo; - uint32_t fip; - uint32_t fdp; - uint16_t fcs; - uint16_t fds; - floatx80 st_space[8]; - unsigned char tos; - unsigned char align1; - unsigned char align2; - unsigned char align3; -} fpu_state_t; - #define in_smm cpu_state._in_smm #define smi_line cpu_state._smi_line @@ -502,7 +484,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; @@ -592,8 +573,6 @@ extern uint32_t eip_msr; extern uint64_t amd_efer; extern uint64_t star; -#define FPU_CW_Reserved_Bits (0xe0c0) - #define cr0 cpu_state.CR0.l #define msw cpu_state.CR0.w extern uint32_t cr2; @@ -637,6 +616,8 @@ extern int cpu_prefetch_width; extern int cpu_mem_prefetch_cycles; extern int cpu_rom_prefetch_cycles; extern int cpu_waitstates; +extern int cpu_flush_pending; +extern int cpu_old_paging; extern int cpu_cache_int_enabled; extern int cpu_cache_ext_enabled; extern int cpu_isa_speed; diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c index 502b2c86e3..5326c9d14d 100644 --- a/src/cpu/cpu_table.c +++ b/src/cpu/cpu_table.c @@ -16,13 +16,15 @@ * Fred N. van Kempen, * RichardG, * dob205, + * Jasmine Iwanek, * * Copyright 2008-2019 Sarah Walker. * Copyright 2016-2019 leilei. - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2024 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2020 RichardG. * Copyright 2021 dob205. + * Copyright 2022-2024 Jasmine Iwanek. */ #include #include @@ -71,1912 +73,7927 @@ FPU fpus_internal[] = { const cpu_family_t cpu_families[] = { // clang-format off { - .package = CPU_PKG_8088, - .manufacturer = "Intel", - .name = "8088", - .internal_name = "8088", - .cpus = (const CPU[]) { - { - .name = "4.77", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 4772728, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "7.16", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 7159092, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "8", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 8000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, + .package = CPU_PKG_8088, + .manufacturer = "Intel", + .name = "8088", + .internal_name = "8088", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, #if 0 - { - .name = "9.54", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 9545456, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, + { + .name = "9.54", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, #endif - { - .name = "10", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 10000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 12000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "16", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 16000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_8088_EUROPC, - .manufacturer = "Intel", - .name = "8088", - .internal_name = "8088_europc", - .cpus = (const CPU[]) { - { - .name = "4.77", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 4772728, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "7.16", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 7159092, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "9.54", - .cpu_type = CPU_8088, - .fpus = fpus_8088, - .rspeed = 9545456, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_8086, - .manufacturer = "Intel", - .name = "8086", - .internal_name = "8086", - .cpus = (const CPU[]) { - { - .name = "7.16", - .cpu_type = CPU_8086, - .fpus = fpus_8088, - .rspeed = 7159092, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "8", - .cpu_type = CPU_8086, - .fpus = fpus_8088, - .rspeed = 8000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "9.54", - .cpu_type = CPU_8086, - .fpus = fpus_8088, - .rspeed = 9545456, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "10", - .cpu_type = CPU_8086, - .fpus = fpus_8088, - .rspeed = 10000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_8086, - .fpus = fpus_8088, - .rspeed = 12000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "16", - .cpu_type = CPU_8086, - .fpus = fpus_8088, - .rspeed = 16000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 2 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_188, - .manufacturer = "Intel", - .name = "80188", - .internal_name = "80188", - .cpus = (const CPU[]) { - { - .name = "6", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 6000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "7.16", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 7159092, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "8", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 8000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "9.54", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 9545456, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "10", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 10000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 12000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "16", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 16000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 2 - }, - { - .name = "20", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 20000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 3 - }, - { - .name = "25", - .cpu_type = CPU_188, - .fpus = fpus_8088, - .rspeed = 25000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 3 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_8088, - .manufacturer = "NEC", - .name = "V20", - .internal_name = "necv20", - .cpus = (const CPU[]) { - { - .name = "4.77", - .cpu_type = CPU_V20, - .fpus = fpus_8088, - .rspeed = 4772728, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "7.16", - .cpu_type = CPU_V20, - .fpus = fpus_8088, - .rspeed = 7159092, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "10", - .cpu_type = CPU_V20, - .fpus = fpus_8088, - .rspeed = 10000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_V20, - .fpus = fpus_8088, - .rspeed = 12000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "16", - .cpu_type = CPU_V20, - .fpus = fpus_8088, - .rspeed = 16000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 2 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_186, - .manufacturer = "Intel", - .name = "80186", - .internal_name = "80186", - .cpus = (const CPU[]) { - { - .name = "6", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 6000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "7.16", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 7159092, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "8", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 8000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "9.54", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 9545456, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = CPU_ALTERNATE_XTAL, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "10", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 10000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 12000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "16", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 16000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 2 - }, - { - .name = "20", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 20000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 3 - }, - { - .name = "25", - .cpu_type = CPU_186, - .fpus = fpus_80186, - .rspeed = 25000000, - .multi = 1, - .voltage = 0, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 3 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_8086, - .manufacturer = "NEC", - .name = "V30", - .internal_name = "necv30", - .cpus = (const CPU[]) { - { - .name = "5", - .cpu_type = CPU_V30, - .fpus = fpus_80186, - .rspeed = 5000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "8", - .cpu_type = CPU_V30, - .fpus = fpus_80186, - .rspeed = 8000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "10", - .cpu_type = CPU_V30, - .fpus = fpus_80186, - .rspeed = 10000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_V30, - .fpus = fpus_80186, - .rspeed = 12000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 1 - }, - { - .name = "16", - .cpu_type = CPU_V30, - .fpus = fpus_80186, - .rspeed = 16000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 0, - .mem_write_cycles = 0, - .cache_read_cycles = 0, - .cache_write_cycles = 0, - .atclk_div = 2 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_286, - .manufacturer = "Intel", - .name = "80286", - .internal_name = "286", - .cpus = (const CPU[]) { - { - .name = "6", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 6000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 2, - .mem_write_cycles = 2, - .cache_read_cycles = 2, - .cache_write_cycles = 2, - .atclk_div = 1 - }, - { - .name = "8", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 8000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 2, - .mem_write_cycles = 2, - .cache_read_cycles = 2, - .cache_write_cycles = 2, - .atclk_div = 1 - }, - { - .name = "10", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 10000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 2, - .mem_write_cycles = 2, - .cache_read_cycles = 2, - .cache_write_cycles = 2, - .atclk_div = 1 - }, - { - .name = "12", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 12500000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 3, - .mem_write_cycles = 3, - .cache_read_cycles = 3, - .cache_write_cycles = 3, - .atclk_div = 2 - }, - { - .name = "16", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 16000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 3, - .mem_write_cycles = 3, - .cache_read_cycles = 3, - .cache_write_cycles = 3, - .atclk_div = 2 - }, - { - .name = "20", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 20000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 4, - .mem_write_cycles = 4, - .cache_read_cycles = 4, - .cache_write_cycles = 4, - .atclk_div = 3 - }, - { - .name = "25", - .cpu_type = CPU_286, - .fpus = fpus_80286, - .rspeed = 25000000, - .multi = 1, - .voltage = 5000, - .edx_reset = 0, - .cpuid_model = 0, - .cyrix_id = 0, - .cpu_flags = 0, - .mem_read_cycles = 4, - .mem_write_cycles = 4, - .cache_read_cycles = 4, - .cache_write_cycles = 4, - .atclk_div = 3 - }, - { .name = "", 0 } - } - }, { - .package = CPU_PKG_386SX, - .manufacturer = "Intel", - .name = "i386SX", - .internal_name = "i386sx", - .cpus = (const CPU[]) { - {"16", CPU_386SX, fpus_80386, 16000000, 1, 5000, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386SX, fpus_80386, 20000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386SX, fpus_80386, 25000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386SX, fpus_80386, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_80386, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_386SX, - .manufacturer = "AMD", - .name = "Am386SX", - .internal_name = "am386sx", - .cpus = (const CPU[]) { - {"16", CPU_386SX, fpus_80386, 16000000, 1, 5000, 0x2308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386SX, fpus_80386, 20000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386SX, fpus_80386, 25000000, 1, 5000, 0x2308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386SX, fpus_80386, 33333333, 1, 5000, 0x2308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_80386, 40000000, 1, 5000, 0x2308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_386DX, - .manufacturer = "Intel", - .name = "i386DX", - .internal_name = "i386dx", - .cpus = (const CPU[]) { - {"16", CPU_386DX, fpus_80386, 16000000, 1, 5000, 0x0308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386DX, fpus_80386, 20000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386DX, fpus_80386, 33333333, 1, 5000, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386DX, fpus_80386, 40000000, 1, 5000, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_386DX_DESKPRO386, - .manufacturer = "Intel", - .name = "i386DX", - .internal_name = "i386dx_deskpro386", - .cpus = (const CPU[]) { - {"16", CPU_386DX, fpus_80286, 16000000, 1, 5000, 0x0308, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_386DX, fpus_80386, 20000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"", 0} - } - }, { - .package = CPU_PKG_386DX, - .manufacturer = "Intel", - .name = "RapidCAD", - .internal_name = "rapidcad", - .cpus = (const CPU[]) { - {"25", CPU_RAPIDCAD, fpus_internal, 25000000, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3}, - {"33", CPU_RAPIDCAD, fpus_internal, 33333333, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4}, - {"40", CPU_RAPIDCAD, fpus_internal, 40000000, 1, 5000, 0x0340, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_386DX, - .manufacturer = "AMD", - .name = "Am386DX", - .internal_name = "am386dx", - .cpus = (const CPU[]) { - {"25", CPU_386DX, fpus_80386, 25000000, 1, 5000, 0x0308, 0, 0, 0, 4,4,3,3, 3}, - {"33", CPU_386DX, fpus_80386, 33333333, 1, 5000, 0x0308, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386DX, fpus_80386, 40000000, 1, 5000, 0x0308, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_M6117, - .manufacturer = "ALi", - .name = "M6117", - .internal_name = "m6117", - .cpus = (const CPU[]) { /* All timings and edx_reset values assumed. */ - {"33", CPU_386SX, fpus_none, 33333333, 1, 5000, 0x2309, 0, 0, 0, 6,6,3,3, 4}, - {"40", CPU_386SX, fpus_none, 40000000, 1, 5000, 0x2309, 0, 0, 0, 7,7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_386SLC_IBM, - .manufacturer = "IBM", - .name = "386SLC", - .internal_name = "ibm386slc", - .cpus = (const CPU[]) { - {"16", CPU_IBM386SLC, fpus_80386, 16000000, 1, 5000, 0xA301, 0, 0, 0, 3,3,3,3, 2}, - {"20", CPU_IBM386SLC, fpus_80386, 20000000, 1, 5000, 0xA301, 0, 0, 0, 4,4,3,3, 3}, - {"25", CPU_IBM386SLC, fpus_80386, 25000000, 1, 5000, 0xA301, 0, 0, 0, 4,4,3,3, 3}, - {"", 0} - } - }, { - .package = CPU_PKG_386SX, - .manufacturer = "Cyrix", - .name = "Cx486SLC", - .internal_name = "cx486slc", - .cpus = (const CPU[]) { - {"20", CPU_486SLC, fpus_80386, 20000000, 1, 5000, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"25", CPU_486SLC, fpus_80386, 25000000, 1, 5000, 0x400, 0, 0x0000, 0, 4,4,3,3, 3}, - {"33", CPU_486SLC, fpus_80386, 33333333, 1, 5000, 0x400, 0, 0x0000, 0, 6,6,3,3, 4}, - {"", 0} - } - }, { - .package = CPU_PKG_386SX, - .manufacturer = "Cyrix", - .name = "Cx486SRx2", - .internal_name = "cx486srx2", - .cpus = (const CPU[]) { - {"32", CPU_486SLC, fpus_80386, 32000000, 2, 5000, 0x406, 0, 0x0006, 0, 6,6,6,6, 4}, - {"40", CPU_486SLC, fpus_80386, 40000000, 2, 5000, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, - {"50", CPU_486SLC, fpus_80386, 50000000, 2, 5000, 0x406, 0, 0x0006, 0, 8,8,6,6, 6}, - {"", 0} - } - }, { - .package = CPU_PKG_486SLC_IBM, - .manufacturer = "IBM", - .name = "486SLC", - .internal_name = "ibm486slc", - .cpus = (const CPU[]) { - {"33", CPU_IBM486SLC, fpus_80386, 33333333, 1, 5000, 0xA401, 0, 0, 0, 6,6,3,3, 4}, - {"", 0} - } - }, { - .package = CPU_PKG_486SLC_IBM, - .manufacturer = "IBM", - .name = "486SLC2", - .internal_name = "ibm486slc2", - .cpus = (const CPU[]) { - {"40", CPU_IBM486SLC, fpus_80386, 40000000, 2, 5000, 0xA421, 0, 0, 0, 7,7,6,6, 5}, - {"50", CPU_IBM486SLC, fpus_80386, 50000000, 2, 5000, 0xA421, 0, 0, 0, 8,8,6,6, 6}, - {"66", CPU_IBM486SLC, fpus_80386, 66666666, 2, 5000, 0xA421, 0, 0, 0, 12,12,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_486SLC_IBM, - .manufacturer = "IBM", - .name = "486SLC3", - .internal_name = "ibm486slc3", - .cpus = (const CPU[]) { - {"60", CPU_IBM486SLC, fpus_80386, 60000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 7}, - {"75", CPU_IBM486SLC, fpus_80386, 75000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 9}, - {"100", CPU_IBM486SLC, fpus_80386, 100000000, 3, 5000, 0xA439, 0, 0, 0, 18,18,9,9, 12}, - {"", 0} - } - }, { - .package = CPU_PKG_486BL, - .manufacturer = "IBM", - .name = "486BL2", - .internal_name = "ibm486bl2", - .cpus = (const CPU[]) { - {"50", CPU_IBM486BL, fpus_80386, 50000000, 2, 5000, 0xA439, 0, 0, 0, 8,8,6,6, 6}, - {"66", CPU_IBM486BL, fpus_80386, 66666666, 2, 5000, 0xA439, 0, 0, 0, 12,12,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_486BL, - .manufacturer = "IBM", - .name = "486BL3", - .internal_name = "ibm486bl3", - .cpus = (const CPU[]) { - {"75", CPU_IBM486BL, fpus_80386, 75000000, 3, 5000, 0xA439, 0, 0, 0, 12,12,9,9, 9}, - {"100", CPU_IBM486BL, fpus_80386, 100000000, 3, 5000, 0xA439, 0, 0, 0, 18,18,9,9, 12}, - {"", 0} - } - }, { - .package = CPU_PKG_386DX, - .manufacturer = "Cyrix", - .name = "Cx486DLC", - .internal_name = "cx486dlc", - .cpus = (const CPU[]) { - {"25", CPU_486DLC, fpus_80386, 25000000, 1, 5000, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3}, - {"33", CPU_486DLC, fpus_80386, 33333333, 1, 5000, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4}, - {"40", CPU_486DLC, fpus_80386, 40000000, 1, 5000, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_386DX, - .manufacturer = "Cyrix", - .name = "Cx486DRx2", - .internal_name = "cx486drx2", - .cpus = (const CPU[]) { - {"32", CPU_486DLC, fpus_80386, 32000000, 2, 5000, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4}, - {"40", CPU_486DLC, fpus_80386, 40000000, 2, 5000, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6}, - {"50", CPU_486DLC, fpus_80386, 50000000, 2, 5000, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6}, - {"66", CPU_486DLC, fpus_80386, 66666666, 2, 5000, 0x407, 0, 0x0007, 0, 12,12,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486SX", - .internal_name = "i486sx", - .cpus = (const CPU[]) { - {"16", CPU_i486SX, fpus_486sx, 16000000, 1, 5000, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2}, - {"20", CPU_i486SX, fpus_486sx, 20000000, 1, 5000, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"25", CPU_i486SX, fpus_486sx, 25000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"33", CPU_i486SX, fpus_486sx, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486SX-S", - .internal_name = "i486sx_slenh", - .cpus = (const CPU[]) { - {"25", CPU_i486SX_SLENH, fpus_486sx, 25000000, 1, 5000, 0x423, 0x423, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"33", CPU_i486SX_SLENH, fpus_486sx, 33333333, 1, 5000, 0x42a, 0x42a, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486SX2", - .internal_name = "i486sx2", - .cpus = (const CPU[]) { - {"50", CPU_i486SX_SLENH, fpus_486sx, 50000000, 2, 5000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66 (Q0569)", CPU_i486SX_SLENH, fpus_486sx, 66666666, 2, 5000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX", - .internal_name = "i486dx", - .cpus = (const CPU[]) { - {"25", CPU_i486DX, fpus_internal, 25000000, 1, 5000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3}, - {"33", CPU_i486DX, fpus_internal, 33333333, 1, 5000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"50", CPU_i486DX, fpus_internal, 50000000, 1, 5000, 0x411, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX-S", - .internal_name = "i486dx_slenh", - .cpus = (const CPU[]) { - {"33", CPU_i486DX_SLENH, fpus_internal, 33333333, 1, 5000, 0x414, 0x414, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4}, - {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 1, 5000, 0x414, 0x414, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX2", - .internal_name = "i486dx2", - .cpus = (const CPU[]) { - {"40", CPU_i486DX, fpus_internal, 40000000, 2, 5000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, - {"50", CPU_i486DX, fpus_internal, 50000000, 2, 5000, 0x433, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66", CPU_i486DX, fpus_internal, 66666666, 2, 5000, 0x433, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Intel", - .name = "i486DX2-S", - .internal_name = "i486dx2_slenh", - .cpus = (const CPU[]) { - {"40", CPU_i486DX_SLENH, fpus_internal, 40000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, - {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66", CPU_i486DX_SLENH, fpus_internal, 66666666, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, - .manufacturer = "Intel", - .name = "i486DX2 WB", - .internal_name = "i486dx2_pc330", - .cpus = (const CPU[]) { - {"50", CPU_i486DX_SLENH, fpus_internal, 50000000, 2, 5000, 0x436, 0x436, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6}, - {"66", CPU_i486DX_SLENH, fpus_internal, 66666666, 2, 5000, 0x436, 0x436, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, /*OEM versions are 3.3V, Retail versions are 3.3V with a 5V regulator for installation in older boards. They are functionally identical*/ - .manufacturer = "Intel", - .name = "iDX4", - .internal_name = "idx4", - .cpus = (const CPU[]) { - {"75", CPU_i486DX_SLENH, fpus_internal, 75000000, 3.0, 5000, 0x480, 0x480, 0x0000, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"100", CPU_i486DX_SLENH, fpus_internal, 100000000, 3.0, 5000, 0x483, 0x483, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET3_PC330, - .manufacturer = "Intel", - .name = "Pentium OverDrive", - .internal_name = "pentium_p24t", - .cpus = (const CPU[]) { - {"63", CPU_P24T, fpus_internal, 62500000, 2.5, 5000, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2}, - {"83", CPU_P24T, fpus_internal, 83333333, 2.5, 5000, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486SX", - .internal_name = "am486sx", - .cpus = (const CPU[]) { - {"33", CPU_Am486SX, fpus_486sx, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Am486SX, fpus_486sx, 40000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486SX2", - .internal_name = "am486sx2", - .cpus = (const CPU[]) { - {"50", CPU_Am486SX, fpus_486sx, 50000000, 2, 5000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Am486SX, fpus_486sx, 66666666, 2, 5000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DX", - .internal_name = "am486dx", - .cpus = (const CPU[]) { - {"33", CPU_Am486DX, fpus_internal, 33333333, 1, 5000, 0x412, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Am486DX, fpus_internal, 40000000, 1, 5000, 0x412, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DX2", - .internal_name = "am486dx2", - .cpus = (const CPU[]) { - {"50", CPU_Am486DX, fpus_internal, 50000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Am486DX, fpus_internal, 66666666, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_Am486DX, fpus_internal, 80000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DXL", - .internal_name = "am486dxl", - .cpus = (const CPU[]) { - {"33", CPU_Am486DXL, fpus_internal, 33333333, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Am486DXL, fpus_internal, 40000000, 1, 5000, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "AMD", - .name = "Am486DXL2", - .internal_name = "am486dxl2", - .cpus = (const CPU[]) { - {"50", CPU_Am486DXL, fpus_internal, 50000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Am486DXL, fpus_internal, 66666666, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_Am486DXL, fpus_internal, 80000000, 2, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am486DX4", - .internal_name = "am486dx4", - .cpus = (const CPU[]) { - {"75", CPU_Am486DX, fpus_internal, 75000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"90", CPU_Am486DX, fpus_internal, 90000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"100", CPU_Am486DX, fpus_internal, 100000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"120", CPU_Am486DX, fpus_internal, 120000000, 3.0, 5000, 0x432, 0, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am486DX2 (Enhanced)", - .internal_name = "am486dx2_slenh", - .cpus = (const CPU[]) { - {"66", CPU_ENH_Am486DX, fpus_internal, 66666666, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_ENH_Am486DX, fpus_internal, 80000000, 2, 5000, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am486DX4 (Enhanced)", - .internal_name = "am486dx4_slenh", - .cpus = (const CPU[]) { - {"75", CPU_ENH_Am486DX, fpus_internal, 75000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"100", CPU_ENH_Am486DX, fpus_internal, 100000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"120", CPU_ENH_Am486DX, fpus_internal, 120000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "AMD", - .name = "Am5x86", - .internal_name = "am5x86", - .cpus = (const CPU[]) { - {"133 (P75)", CPU_ENH_Am486DX, fpus_internal, 133333333, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"150 (P75+)", CPU_ENH_Am486DX, fpus_internal, 150000000, 3.0, 5000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ - {"160 (P90)", CPU_ENH_Am486DX, fpus_internal, 160000000, 4.0, 5000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Cyrix", - .name = "Cx486S", - .internal_name = "cx486s", - .cpus = (const CPU[]) { - {"25", CPU_Cx486S, fpus_486sx, 25000000, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3}, - {"33", CPU_Cx486S, fpus_486sx, 33333333, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Cx486S, fpus_486sx, 40000000, 1.0, 5000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Cyrix", - .name = "Cx486DX", - .internal_name = "cx486dx", - .cpus = (const CPU[]) { - {"33", CPU_Cx486DX, fpus_internal, 33333333, 1.0, 5000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4}, - {"40", CPU_Cx486DX, fpus_internal, 40000000, 1.0, 5000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET1, - .manufacturer = "Cyrix", - .name = "Cx486DX2", - .internal_name = "cx486dx2", - .cpus = (const CPU[]) { - {"50", CPU_Cx486DX, fpus_internal, 50000000, 2.0, 5000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, - {"66", CPU_Cx486DX, fpus_internal, 66666666, 2.0, 5000, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, - {"80", CPU_Cx486DX, fpus_internal, 80000000, 2.0, 5000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "Cyrix", - .name = "Cx486DX4", - .internal_name = "cx486dx4", - .cpus = (const CPU[]) { - {"75", CPU_Cx486DX, fpus_internal, 75000000, 3.0, 5000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9}, - {"100", CPU_Cx486DX, fpus_internal, 100000000, 3.0, 5000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET3, - .manufacturer = "Cyrix", - .name = "Cx5x86", - .internal_name = "cx5x86", - .cpus = (const CPU[]) { - {"80", CPU_Cx5x86, fpus_internal, 80000000, 2.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/ - {"100", CPU_Cx5x86, fpus_internal, 100000000, 3.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12}, - {"120", CPU_Cx5x86, fpus_internal, 120000000, 3.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15}, - {"133", CPU_Cx5x86, fpus_internal, 133333333, 4.0, 5000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16}, - {"", 0} - } - }, { - .package = CPU_PKG_STPC, - .manufacturer = "ST", - .name = "STPC-DX", - .internal_name = "stpc_dx", - .cpus = (const CPU[]) { - {"66", CPU_STPC, fpus_internal, 66666666, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"75", CPU_STPC, fpus_internal, 75000000, 1.0, 3300, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5}, - {"", 0} - } - }, { - .package = CPU_PKG_STPC, - .manufacturer = "ST", - .name = "STPC-DX2", - .internal_name = "stpc_dx2", - .cpus = (const CPU[]) { - {"133", CPU_STPC, fpus_internal, 133333333, 2.0, 3300, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET4, - .manufacturer = "Intel", - .name = "Pentium", - .internal_name = "pentium_p5", - .cpus = (const CPU[]) { - {"50 (Q0399)", CPU_PENTIUM, fpus_internal, 50000000, 1, 5000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 4, 4,3,3, 6}, - {"60", CPU_PENTIUM, fpus_internal, 60000000, 1, 5000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6,3,3, 7}, - {"66", CPU_PENTIUM, fpus_internal, 66666666, 1, 5000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6,3,3, 8}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET4, - .manufacturer = "Intel", - .name = "Pentium OverDrive", - .internal_name = "pentium_p54c_od5v", - .cpus = (const CPU[]) { - {"100", CPU_PENTIUM, fpus_internal, 100000000, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 8, 8,6,6, 12}, - {"120", CPU_PENTIUM, fpus_internal, 120000000, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,6,6, 14}, - {"133", CPU_PENTIUM, fpus_internal, 133333333, 2, 5000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,6,6, 16}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium", - .internal_name = "pentium_p54c", - .cpus = (const CPU[]) { - {"75", CPU_PENTIUM, fpus_internal, 75000000, 1.5, 3520, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"90", CPU_PENTIUM, fpus_internal, 90000000, 1.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"100/50", CPU_PENTIUM, fpus_internal, 100000000, 2.0, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12}, - {"100/66", CPU_PENTIUM, fpus_internal, 100000000, 1.5, 3520, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"120", CPU_PENTIUM, fpus_internal, 120000000, 2.0, 3520, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"133", CPU_PENTIUM, fpus_internal, 133333333, 2.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"150", CPU_PENTIUM, fpus_internal, 150000000, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"166", CPU_PENTIUM, fpus_internal, 166666666, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_PENTIUM, fpus_internal, 200000000, 3.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium MMX", - .internal_name = "pentium_p55c", - .cpus = (const CPU[]) { - {"166", CPU_PENTIUMMMX, fpus_internal, 166666666, 2.5, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_PENTIUMMMX, fpus_internal, 233333333, 3.5, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Mobile Pentium MMX", - .internal_name = "pentium_tillamook", - .cpus = (const CPU[]) { - {"120", CPU_PENTIUMMMX, fpus_internal, 120000000, 2.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"133", CPU_PENTIUMMMX, fpus_internal, 133333333, 2.0, 2800, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"150", CPU_PENTIUMMMX, fpus_internal, 150000000, 2.5, 2800, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"166", CPU_PENTIUMMMX, fpus_internal, 166666666, 2.5, 2800, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 2800, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_PENTIUMMMX, fpus_internal, 233333333, 3.5, 2800, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"266", CPU_PENTIUMMMX, fpus_internal, 266666666, 4.0, 2800, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_PENTIUMMMX, fpus_internal, 300000000, 4.5, 2800, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium OverDrive", - .internal_name = "pentium_p54c_od3v", - .cpus = (const CPU[]) { - {"125", CPU_PENTIUM, fpus_internal, 125000000, 3.0, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,7,7, 15}, - {"150", CPU_PENTIUM, fpus_internal, 150000000, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 35/2}, - {"166", CPU_PENTIUM, fpus_internal, 166666666, 2.5, 3520, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 20}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Intel", - .name = "Pentium OverDrive MMX", - .internal_name = "pentium_p55c_od", - .cpus = (const CPU[]) { - {"75", CPU_PENTIUMMMX, fpus_internal, 75000000, 1.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 7, 7,4,4, 9}, - {"125", CPU_PENTIUMMMX, fpus_internal, 125000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12,7,7, 15}, - {"150/60", CPU_PENTIUMMMX, fpus_internal, 150000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 35/2}, - {"166", CPU_PENTIUMMMX, fpus_internal, 166000000, 2.5, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15,7,7, 20}, - {"180", CPU_PENTIUMMMX, fpus_internal, 180000000, 3.0, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18,9,9, 21}, - {"200", CPU_PENTIUMMMX, fpus_internal, 200000000, 3.0, 3520, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18,9,9, 24}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "IDT", - .name = "WinChip", - .internal_name = "winchip", - .cpus = (const CPU[]) { - {"75", CPU_WINCHIP, fpus_internal, 75000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9}, - {"90", CPU_WINCHIP, fpus_internal, 90000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2}, - {"100", CPU_WINCHIP, fpus_internal, 100000000, 1.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12}, - {"120", CPU_WINCHIP, fpus_internal, 120000000, 2.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14}, - {"133", CPU_WINCHIP, fpus_internal, 133333333, 2.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16}, - {"150", CPU_WINCHIP, fpus_internal, 150000000, 2.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2}, - {"166", CPU_WINCHIP, fpus_internal, 166666666, 2.5, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40}, - {"180", CPU_WINCHIP, fpus_internal, 180000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21}, - {"200", CPU_WINCHIP, fpus_internal, 200000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24}, - {"225", CPU_WINCHIP, fpus_internal, 225000000, 3.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27}, - {"240", CPU_WINCHIP, fpus_internal, 240000000, 4.0, 3520, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "IDT", - .name = "WinChip 2", - .internal_name = "winchip2", - .cpus = (const CPU[]) { - {"200", CPU_WINCHIP2, fpus_internal, 200000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"225", CPU_WINCHIP2, fpus_internal, 225000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9}, - {"240", CPU_WINCHIP2, fpus_internal, 240000000, 4.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"250", CPU_WINCHIP2, fpus_internal, 250000000, 3.0, 3520, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "IDT", - .name = "WinChip 2A", - .internal_name = "winchip2a", - .cpus = (const CPU[]) { - {"200", CPU_WINCHIP2, fpus_internal, 200000000, 3.0, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8}, - {"233", CPU_WINCHIP2, fpus_internal, 233333333, 3.5, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2}, - {"266", CPU_WINCHIP2, fpus_internal, 233333333, 7.0/3.0, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28}, - {"300", CPU_WINCHIP2, fpus_internal, 250000000, 2.5, 3520, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30}, - {"", 0} - } - }, -#if defined(DEV_BRANCH) && defined(USE_AMD_K5) - { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K5 (Model 0)", - .internal_name = "k5_ssa5", - .cpus = (const CPU[]) { - {"75 (PR75)", CPU_K5, fpus_internal, 75000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9}, - {"90 (PR90)", CPU_K5, fpus_internal, 90000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2}, - {"100 (PR100)", CPU_K5, fpus_internal, 100000000, 1.5, 3520, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K5 (Model 1/2/3)", - .internal_name = "k5_5k86", - .cpus = (const CPU[]) { - {"90 (PR120)", CPU_5K86, fpus_internal, 120000000, 2.0, 3520, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14}, - {"100 (PR133)", CPU_5K86, fpus_internal, 133333333, 2.0, 3520, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16}, - {"105 (PR150)", CPU_5K86, fpus_internal, 150000000, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2}, - {"116.7 (PR166)", CPU_5K86, fpus_internal, 166666666, 2.5, 3520, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20}, - {"133 (PR200)", CPU_5K86, fpus_internal, 200000000, 3.0, 3520, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24}, - {"", 0} - } + { + .name = "10", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } }, -#endif { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6 (Model 6)", - .internal_name = "k6_m6", - .cpus = (const CPU[]) { - {"66", CPU_K6, fpus_internal, 66666666, 1.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2900, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_K6, fpus_internal, 233333333, 3.5, 3200, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6 (Model 7)", - .internal_name = "k6_m7", - .cpus = (const CPU[]) { - {"100", CPU_K6, fpus_internal, 100000000, 1.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6, fpus_internal, 133333333, 2.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6, fpus_internal, 166666666, 2.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6, fpus_internal, 200000000, 3.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"233", CPU_K6, fpus_internal, 233333333, 3.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"266", CPU_K6, fpus_internal, 266666666, 4.0, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_K6, fpus_internal, 300000000, 4.5, 2200, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-2", - .internal_name = "k6_2", - .cpus = (const CPU[]) { - {"100", CPU_K6_2, fpus_internal, 100000000, 1.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6_2, fpus_internal, 133333333, 2.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_2, fpus_internal, 166666666, 2.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_2, fpus_internal, 200000000, 3.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_2, fpus_internal, 233333333, 3.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, - {"266", CPU_K6_2, fpus_internal, 266666666, 4.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, - {"300", CPU_K6_2, fpus_internal, 300000000, 3.0, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, - {"333", CPU_K6_2, fpus_internal, 332500000, 3.5, 2200, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, - {"350", CPU_K6_2C, fpus_internal, 350000000, 3.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, - {"366", CPU_K6_2C, fpus_internal, 366666666, 5.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, - {"380", CPU_K6_2C, fpus_internal, 380000000, 4.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, - {"400/66", CPU_K6_2C, fpus_internal, 400000000, 6.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"400/100", CPU_K6_2C, fpus_internal, 400000000, 4.0, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"450", CPU_K6_2C, fpus_internal, 450000000, 4.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"475", CPU_K6_2C, fpus_internal, 475000000, 5.0, 2400, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"500", CPU_K6_2C, fpus_internal, 500000000, 5.0, 2400, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"533", CPU_K6_2C, fpus_internal, 533333333, 5.5, 2200, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, - {"550", CPU_K6_2C, fpus_internal, 550000000, 5.5, 2300, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-2+", - .internal_name = "k6_2p", - .cpus = (const CPU[]) { - {"100", CPU_K6_2P, fpus_internal, 100000000, 1.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6_2P, fpus_internal, 133333333, 2.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_2P, fpus_internal, 166666666, 2.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_2P, fpus_internal, 200000000, 3.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_2P, fpus_internal, 233333333, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ - {"266", CPU_K6_2P, fpus_internal, 266666666, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ - {"300", CPU_K6_2P, fpus_internal, 300000000, 3.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ - {"333", CPU_K6_2P, fpus_internal, 332500000, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ - {"350", CPU_K6_2P, fpus_internal, 350000000, 3.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ - {"366", CPU_K6_2P, fpus_internal, 366666666, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ - {"380", CPU_K6_2P, fpus_internal, 380000000, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ - {"400/66", CPU_K6_2P, fpus_internal, 400000000, 6.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, /* out of spec */ - {"400/100", CPU_K6_2P, fpus_internal, 400000000, 4.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, /* out of spec */ - {"450", CPU_K6_2P, fpus_internal, 450000000, 4.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"475", CPU_K6_2P, fpus_internal, 475000000, 5.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"500", CPU_K6_2P, fpus_internal, 500000000, 5.0, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"533", CPU_K6_2P, fpus_internal, 533333333, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64}, - {"550", CPU_K6_2P, fpus_internal, 550000000, 5.5, 2000, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-III", - .internal_name = "k6_3", - .cpus = (const CPU[]) { - {"100", CPU_K6_3, fpus_internal, 100000000, 1.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_K6_3, fpus_internal, 133333333, 2.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_3, fpus_internal, 166666666, 2.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_3, fpus_internal, 200000000, 3.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_3, fpus_internal, 233333333, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ - {"266", CPU_K6_3, fpus_internal, 266666666, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ - {"300", CPU_K6_3, fpus_internal, 300000000, 3.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ - {"333", CPU_K6_3, fpus_internal, 332500000, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ - {"350", CPU_K6_3, fpus_internal, 350000000, 3.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ - {"366", CPU_K6_3, fpus_internal, 366666666, 5.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ - {"380", CPU_K6_3, fpus_internal, 380000000, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ - {"400", CPU_K6_3, fpus_internal, 400000000, 4.0, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"450", CPU_K6_3, fpus_internal, 450000000, 4.5, 2200, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "AMD", - .name = "K6-III+", - .internal_name = "k6_3p", - .cpus = (const CPU[]) { - {"100", CPU_K6_3P, fpus_internal, 100000000, 1.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9}, /* out of spec */ - {"133", CPU_K6_3P, fpus_internal, 133333333, 2.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12, 12, 6, 6, 16}, /* out of spec */ - {"166", CPU_K6_3P, fpus_internal, 166666666, 2.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15, 15, 7, 7, 20}, /* out of spec */ - {"200", CPU_K6_3P, fpus_internal, 200000000, 3.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18, 18, 9, 9, 24}, /* out of spec */ - {"233", CPU_K6_3P, fpus_internal, 233333333, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28}, /* out of spec */ - {"266", CPU_K6_3P, fpus_internal, 266666666, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32}, /* out of spec */ - {"300", CPU_K6_3P, fpus_internal, 300000000, 3.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36}, /* out of spec */ - {"333", CPU_K6_3P, fpus_internal, 332500000, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40}, /* out of spec */ - {"350", CPU_K6_3P, fpus_internal, 350000000, 3.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42}, /* out of spec */ - {"366", CPU_K6_3P, fpus_internal, 366666666, 5.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44}, /* out of spec */ - {"380", CPU_K6_3P, fpus_internal, 380000000, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46}, /* out of spec */ - {"400", CPU_K6_3P, fpus_internal, 400000000, 4.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48}, - {"450", CPU_K6_3P, fpus_internal, 450000000, 4.5, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54}, - {"475", CPU_K6_3P, fpus_internal, 475000000, 5.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57}, - {"500", CPU_K6_3P, fpus_internal, 500000000, 5.0, 2000, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60}, - {"", 0} - } - }, -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "Cx6x86", - .internal_name = "cx6x86", - .cpus = (const CPU[]) { - {"80 (PR90+)", CPU_Cx6x86, fpus_internal, 80000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10}, - {"100 (PR120+)", CPU_Cx6x86, fpus_internal, 100000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12}, - {"110 (PR133+)", CPU_Cx6x86, fpus_internal, 110000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"120 (PR150+)", CPU_Cx6x86, fpus_internal, 120000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"133 (PR166+)", CPU_Cx6x86, fpus_internal, 133333333, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"150 (PR200+)", CPU_Cx6x86, fpus_internal, 150000000, 2.0, 3520, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "Cx6x86L", - .internal_name = "cx6x86l", - .cpus = (const CPU[]) { - {"110 (PR133+)", CPU_Cx6x86L, fpus_internal, 110000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14}, - {"120 (PR150+)", CPU_Cx6x86L, fpus_internal, 120000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14}, - {"133 (PR166+)", CPU_Cx6x86L, fpus_internal, 133333333, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"150 (PR200+)", CPU_Cx6x86L, fpus_internal, 150000000, 2.0, 2800, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "Cx6x86MX", - .internal_name = "cx6x86mx", - .cpus = (const CPU[]) { - {"133 (PR166)", CPU_Cx6x86MX, fpus_internal, 133333333, 2.0, 2900, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, - {"166 (PR200)", CPU_Cx6x86MX, fpus_internal, 166666666, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"187.5 (PR233)", CPU_Cx6x86MX, fpus_internal, 187500000, 2.5, 2900, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2}, - {"208.3 (PR266)", CPU_Cx6x86MX, fpus_internal, 208333333, 2.5, 2700, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET5_7, - .manufacturer = "Cyrix", - .name = "MII", - .internal_name = "mii", - .cpus = (const CPU[]) { - {"233 (PR300)", CPU_Cx6x86MX, fpus_internal, 233333333, 3.5, 2900, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, - {"250/83 (PR333)", CPU_Cx6x86MX, fpus_internal, 250000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30}, - {"250/100 (PR366)", CPU_Cx6x86MX, fpus_internal, 250000000, 2.5, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30}, - {"285 (PR400)", CPU_Cx6x86MX, fpus_internal, 285000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34}, - {"300 (PR433)", CPU_Cx6x86MX, fpus_internal, 300000000, 3.0, 2900, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, - {"", 0} - } + .package = CPU_PKG_8088_EUROPC, + .manufacturer = "Intel", + .name = "8088", + .internal_name = "8088_europc", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_8088, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { .name = "", 0 } + } }, -#endif { - .package = CPU_PKG_SOCKET8, - .manufacturer = "Intel", - .name = "Pentium Pro", - .internal_name = "pentiumpro", - .cpus = (const CPU[]) { - {"60", CPU_PENTIUMPRO, fpus_internal, 60000000, 1.0, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 1, 1, 7}, /* out of spec */ - {"66", CPU_PENTIUMPRO, fpus_internal, 66666666, 1.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 1, 1, 8}, /* out of spec */ - {"90", CPU_PENTIUMPRO, fpus_internal, 90000000, 1.5, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 11}, /* out of spec */ - {"100", CPU_PENTIUMPRO, fpus_internal, 100000000, 1.5, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 12}, /* out of spec */ - {"120", CPU_PENTIUMPRO, fpus_internal, 120000000, 2.0, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 5, 5, 14}, /* out of spec */ - {"133", CPU_PENTIUMPRO, fpus_internal, 133333333, 2.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 5, 5, 16}, /* out of spec */ - {"150", CPU_PENTIUMPRO, fpus_internal, 150000000, 2.5, 3100, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2}, - {"166", CPU_PENTIUMPRO, fpus_internal, 166666666, 2.5, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, - {"180", CPU_PENTIUMPRO, fpus_internal, 180000000, 3.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21}, - {"200", CPU_PENTIUMPRO, fpus_internal, 200000000, 3.0, 3300, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, - {"", 0} - } - }, { - .package = CPU_PKG_SOCKET8, - .manufacturer = "Intel", - .name = "Pentium II OverDrive", - .internal_name = "pentium2_od", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 18,18, 9, 9, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 21,21,10,10, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 24,24,12,12, 32}, /* out of spec */ - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 5.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 36}, - {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 3300, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 40}, - {"", 0} - } - }, { - .package = CPU_PKG_SLOT1, - .manufacturer = "Intel", - .name = "Pentium II (Klamath)", - .internal_name = "pentium2_klamath", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2, fpus_internal, 66666666, 1.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2, fpus_internal, 100000000, 1.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12}, /* out of spec */ - {"133", CPU_PENTIUM2, fpus_internal, 133333333, 2.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_PENTIUM2, fpus_internal, 166666666, 2.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2, fpus_internal, 200000000, 3.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, /* out of spec */ - {"233", CPU_PENTIUM2, fpus_internal, 233333333, 3.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28}, - {"266", CPU_PENTIUM2, fpus_internal, 266666666, 4.0, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_PENTIUM2, fpus_internal, 300000000, 4.5, 2800, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"", 0} - } - }, { - .package = CPU_PKG_SLOT1, - .manufacturer = "Intel", - .name = "Pentium II (Deschutes)", - .internal_name = "pentium2_deschutes", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 5, 5, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32}, - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36}, - {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40}, - {"350", CPU_PENTIUM2D, fpus_internal, 350000000, 3.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,11,11, 42}, - {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48}, - {"450", CPU_PENTIUM2D, fpus_internal, 450000000, 4.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54}, - {"", 0} - } + .package = CPU_PKG_8086, + .manufacturer = "Intel", + .name = "8086", + .internal_name = "8086", + .cpus = (const CPU[]) { + { + .name = "7.16", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_8086, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_188, + .manufacturer = "Intel", + .name = "80188", + .internal_name = "80188", + .cpus = (const CPU[]) { + { + .name = "6", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 6000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 9545456, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_188, + .fpus = fpus_8088, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_8088, + .manufacturer = "NEC", + .name = "V20", + .internal_name = "necv20", + .cpus = (const CPU[]) { + { + .name = "4.77", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 4772728, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 7159092, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_V20, + .fpus = fpus_8088, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_186, + .manufacturer = "Intel", + .name = "80186", + .internal_name = "80186", + .cpus = (const CPU[]) { + { + .name = "6", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 6000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "7.16", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 7159092, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 8000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "9.54", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 9545456, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_ALTERNATE_XTAL, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 10000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 12000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 16000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 20000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_186, + .fpus = fpus_80186, + .rspeed = 25000000, + .multi = 1, + .voltage = 0, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 3 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_8086, + .manufacturer = "NEC", + .name = "V30", + .internal_name = "necv30", + .cpus = (const CPU[]) { + { + .name = "5", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 5000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 12000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 1 + }, + { + .name = "16", + .cpu_type = CPU_V30, + .fpus = fpus_80186, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 0, + .mem_write_cycles = 0, + .cache_read_cycles = 0, + .cache_write_cycles = 0, + .atclk_div = 2 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_286, + .manufacturer = "Intel", + .name = "80286", + .internal_name = "286", + .cpus = (const CPU[]) { + { + .name = "6", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 6000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "8", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 8000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "10", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 10000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 2, + .mem_write_cycles = 2, + .cache_read_cycles = 2, + .cache_write_cycles = 2, + .atclk_div = 1 + }, + { + .name = "12", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 12500000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "16", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_286, + .fpus = fpus_80286, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 3 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386SX, + .manufacturer = "Intel", + .name = "i386SX", + .internal_name = "i386sx", + .cpus = (const CPU[]) { + { + .name = "16", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386SX, + .manufacturer = "AMD", + .name = "Am386SX", + .internal_name = "am386sx", + .cpus = (const CPU[]) { + { + .name = "16", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_386SX, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386DX, + .manufacturer = "Intel", + .name = "i386DX", + .internal_name = "i386dx", + .cpus = (const CPU[]) { + { + .name = "16", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386DX_DESKPRO386, + .manufacturer = "Intel", + .name = "i386DX", + .internal_name = "i386dx_deskpro386", + .cpus = (const CPU[]) { + { + .name = "16", + .cpu_type = CPU_386DX, + .fpus = fpus_80286, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386DX, + .manufacturer = "Intel", + .name = "RapidCAD", + .internal_name = "rapidcad", + .cpus = (const CPU[]) { + { + .name = "25", + .cpu_type = CPU_RAPIDCAD, + .fpus = fpus_internal, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0340, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_RAPIDCAD, + .fpus = fpus_internal, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0340, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_RAPIDCAD, + .fpus = fpus_internal, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0340, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386DX, + .manufacturer = "AMD", + .name = "Am386DX", + .internal_name = "am386dx", + .cpus = (const CPU[]) { + { + .name = "25", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_386DX, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x0308, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_M6117, + .manufacturer = "ALi", + .name = "M6117", + .internal_name = "m6117", + .cpus = (const CPU[]) { /* All timings and edx_reset values assumed. */ + { + .name = "33", + .cpu_type = CPU_386SX, + .fpus = fpus_none, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2309, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_386SX, + .fpus = fpus_none, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x2309, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386SLC_IBM, + .manufacturer = "IBM", + .name = "386SLC", + .internal_name = "ibm386slc", + .cpus = (const CPU[]) { + { + .name = "16", + .cpu_type = CPU_IBM386SLC, + .fpus = fpus_80386, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0xA301, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_IBM386SLC, + .fpus = fpus_80386, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0xA301, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_IBM386SLC, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0xA301, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386SX, + .manufacturer = "Cyrix", + .name = "Cx486SLC", + .internal_name = "cx486slc", + .cpus = (const CPU[]) { + { + .name = "20", + .cpu_type = CPU_486SLC, + .fpus = fpus_80386, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x400, + .cpuid_model = 0, + .cyrix_id = 0x0000, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_486SLC, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x400, + .cpuid_model = 0, + .cyrix_id = 0x0000, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_486SLC, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x400, + .cpuid_model = 0, + .cyrix_id = 0x0000, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386SX, + .manufacturer = "Cyrix", + .name = "Cx486SRx2", + .internal_name = "cx486srx2", + .cpus = (const CPU[]) { + { + .name = "32", + .cpu_type = CPU_486SLC, + .fpus = fpus_80386, + .rspeed = 32000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x406, + .cpuid_model = 0, + .cyrix_id = 0x0006, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_486SLC, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x406, + .cpuid_model = 0, + .cyrix_id = 0x0006, + .cpu_flags = 0, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "50", + .cpu_type = CPU_486SLC, + .fpus = fpus_80386, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x406, + .cpuid_model = 0, + .cyrix_id = 0x0006, + .cpu_flags = 0, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_486SLC_IBM, + .manufacturer = "IBM", + .name = "486SLC", + .internal_name = "ibm486slc", + .cpus = (const CPU[]) { + { + .name = "33", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0xA401, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_486SLC_IBM, + .manufacturer = "IBM", + .name = "486SLC2", + .internal_name = "ibm486slc2", + .cpus = (const CPU[]) { + { + .name = "40", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0xA421, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 5 + }, + { + .name = "50", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0xA421, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0xA421, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_486SLC_IBM, + .manufacturer = "IBM", + .name = "486SLC3", + .internal_name = "ibm486slc3", + .cpus = (const CPU[]) { + { + .name = "60", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 60000000, + .multi = 3, + .voltage = 5000, + .edx_reset = 0xA439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 7 + }, + { + .name = "75", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 75000000, + .multi = 3, + .voltage = 5000, + .edx_reset = 0xA439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 9 + }, + { + .name = "100", + .cpu_type = CPU_IBM486SLC, + .fpus = fpus_80386, + .rspeed = 100000000, + .multi = 3, + .voltage = 5000, + .edx_reset = 0xA439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_486BL, + .manufacturer = "IBM", + .name = "486BL2", + .internal_name = "ibm486bl2", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_IBM486BL, + .fpus = fpus_80386, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x8439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_IBM486BL, + .fpus = fpus_80386, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x8439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_486BL, + .manufacturer = "IBM", + .name = "486BL3", + .internal_name = "ibm486bl3", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_IBM486BL, + .fpus = fpus_80386, + .rspeed = 75000000, + .multi = 3, + .voltage = 5000, + .edx_reset = 0x8439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 9 + }, + { + .name = "100", + .cpu_type = CPU_IBM486BL, + .fpus = fpus_80386, + .rspeed = 100000000, + .multi = 3, + .voltage = 5000, + .edx_reset = 0x8439, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = 0, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386DX, + .manufacturer = "Cyrix", + .name = "Cx486DLC", + .internal_name = "cx486dlc", + .cpus = (const CPU[]) { + { + .name = "25", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x401, + .cpuid_model = 0, + .cyrix_id = 0x0001, + .cpu_flags = 0, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x401, + .cpuid_model = 0, + .cyrix_id = 0x0001, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x401, + .cpuid_model = 0, + .cyrix_id = 0x0001, + .cpu_flags = 0, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_386DX, + .manufacturer = "Cyrix", + .name = "Cx486DRx2", + .internal_name = "cx486drx2", + .cpus = (const CPU[]) { + { + .name = "32", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 32000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x407, + .cpuid_model = 0, + .cyrix_id = 0x0007, + .cpu_flags = 0, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 40000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x407, + .cpuid_model = 0, + .cyrix_id = 0x0007, + .cpu_flags = 0, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "50", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x407, + .cpuid_model = 0, + .cyrix_id = 0x0007, + .cpu_flags = 0, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_486DLC, + .fpus = fpus_80386, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x407, + .cpuid_model = 0, + .cyrix_id = 0x0007, + .cpu_flags = 0, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486SX", + .internal_name = "i486sx", + .cpus = (const CPU[]) { + { + .name = "16", + .cpu_type = CPU_i486SX, + .fpus = fpus_486sx, + .rspeed = 16000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x420, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 3, + .mem_write_cycles = 3, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 2 + }, + { + .name = "20", + .cpu_type = CPU_i486SX, + .fpus = fpus_486sx, + .rspeed = 20000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x420, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "25", + .cpu_type = CPU_i486SX, + .fpus = fpus_486sx, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x422, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_i486SX, + .fpus = fpus_486sx, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x422, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486SX-S", + .internal_name = "i486sx_slenh", + .cpus = (const CPU[]) { + { + .name = "25", + .cpu_type = CPU_i486SX_SLENH, + .fpus = fpus_486sx, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x423, + .cpuid_model = 0x423, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_i486SX_SLENH, + .fpus = fpus_486sx, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x42a, + .cpuid_model = 0x42a, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486SX2", + .internal_name = "i486sx2", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_i486SX_SLENH, + .fpus = fpus_486sx, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x45b, + .cpuid_model = 0x45b, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66 (Q0569)", + .cpu_type = CPU_i486SX_SLENH, + .fpus = fpus_486sx, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x45b, + .cpuid_model = 0x45b, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX", + .internal_name = "i486dx", + .cpus = (const CPU[]) { + { + .name = "25", + .cpu_type = CPU_i486DX, + .fpus = fpus_internal, + .rspeed = 25000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x404, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_i486DX, + .fpus = fpus_internal, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x404, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "50", + .cpu_type = CPU_i486DX, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x411, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 6 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX-S", + .internal_name = "i486dx_slenh", + .cpus = (const CPU[]) { + { + .name = "33", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x414, + .cpuid_model = 0x414, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "50", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x414, + .cpuid_model = 0x414, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 6 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX2", + .internal_name = "i486dx2", + .cpus = (const CPU[]) { + { + .name = "40", + .cpu_type = CPU_i486DX, + .fpus = fpus_internal, + .rspeed = 40000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 5 + }, + { + .name = "50", + .cpu_type = CPU_i486DX, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x433, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_i486DX, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x433, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Intel", + .name = "i486DX2-S", + .internal_name = "i486dx2_slenh", + .cpus = (const CPU[]) { + { + .name = "40", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 40000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x435, + .cpuid_model = 0x435, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 5 + }, + { + .name = "50", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x435, + .cpuid_model = 0x435, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x435, + .cpuid_model = 0x435, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, + .manufacturer = "Intel", + .name = "i486DX2 WB", + .internal_name = "i486dx2_pc330", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x436, + .cpuid_model = 0x436, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x436, + .cpuid_model = 0x436, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { /*OEM versions are 3.3V, Retail versions are 3.3V with a 5V regulator for installation in older boards. They are functionally identical*/ + .package = CPU_PKG_SOCKET1 | CPU_PKG_SOCKET3_PC330, + .manufacturer = "Intel", + .name = "iDX4", + .internal_name = "idx4", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0x480, + .cyrix_id = 0x0000, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 9 + }, + { + .name = "100", + .cpu_type = CPU_i486DX_SLENH, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x483, + .cpuid_model = 0x483, + .cyrix_id = 0x0000, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3 | CPU_PKG_SOCKET3_PC330, + .manufacturer = "Intel", + .name = "Pentium OverDrive", + .internal_name = "pentium_p24t", + .cpus = (const CPU[]) { + { + .name = "63", + .cpu_type = CPU_P24T, + .fpus = fpus_internal, + .rspeed = 62500000, + .multi = 2.5, + .voltage = 5000, + .edx_reset = 0x1531, + .cpuid_model = 0x1531, + .cyrix_id = 0x0000, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 10, + .mem_write_cycles = 10, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 15/2 + }, + { + .name = "83", + .cpu_type = CPU_P24T, + .fpus = fpus_internal, + .rspeed = 83333333, + .multi = 2.5, + .voltage = 5000, + .edx_reset = 0x1532, + .cpuid_model = 0x1532, + .cyrix_id = 0x0000, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 8, + .cache_write_cycles = 8, + .atclk_div = 10 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486SX", + .internal_name = "am486sx", + .cpus = (const CPU[]) { + { + .name = "33", + .cpu_type = CPU_Am486SX, + .fpus = fpus_486sx, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x422, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_Am486SX, + .fpus = fpus_486sx, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x422, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486SX2", + .internal_name = "am486sx2", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_Am486SX, + .fpus = fpus_486sx, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x45b, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_Am486SX, + .fpus = fpus_486sx, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x45b, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DX", + .internal_name = "am486dx", + .cpus = (const CPU[]) { + { + .name = "33", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x412, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x412, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DX2", + .internal_name = "am486dx2", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { + .name = "80", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 80000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DXL", + .internal_name = "am486dxl", + .cpus = (const CPU[]) { + { + .name = "33", + .cpu_type = CPU_Am486DXL, + .fpus = fpus_internal, + .rspeed = 33333333, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x422, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_Am486DXL, + .fpus = fpus_internal, + .rspeed = 40000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x422, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "AMD", + .name = "Am486DXL2", + .internal_name = "am486dxl2", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_Am486DXL, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_Am486DXL, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { + .name = "80", + .cpu_type = CPU_Am486DXL, + .fpus = fpus_internal, + .rspeed = 80000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am486DX4", + .internal_name = "am486dx4", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 9 + }, + { + .name = "90", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 90000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { + .name = "100", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { + .name = "120", + .cpu_type = CPU_Am486DX, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x432, + .cpuid_model = 0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 15 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am486DX2 (Enhanced)", + .internal_name = "am486dx2_slenh", + .cpus = (const CPU[]) { + { + .name = "66", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x435, + .cpuid_model = 0x435, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { + .name = "80", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 80000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x435, + .cpuid_model = 0x435, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am486DX4 (Enhanced)", + .internal_name = "am486dx4_slenh", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x482, + .cpuid_model = 0x482, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 9 + }, + { + .name = "100", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x482, + .cpuid_model = 0x482, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { + .name = "120", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x482, + .cpuid_model = 0x482, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 15 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3, + .manufacturer = "AMD", + .name = "Am5x86", + .internal_name = "am5x86", + .cpus = (const CPU[]) { + { + .name = "133 (P75)", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 4.0, + .voltage = 5000, + .edx_reset = 0x4e0, + .cpuid_model = 0x4e0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 16 + }, + { /*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/ + .name = "150 (P75+)", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x482, + .cpuid_model = 0x482, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 28, + .mem_write_cycles = 28, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 20 + }, + { /*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/ + .name = "160 (P90)", + .cpu_type = CPU_ENH_Am486DX, + .fpus = fpus_internal, + .rspeed = 160000000, + .multi = 4.0, + .voltage = 5000, + .edx_reset = 0x4e0, + .cpuid_model = 0x4e0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 28, + .mem_write_cycles = 28, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 20 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Cyrix", + .name = "Cx486S", + .internal_name = "cx486s", + .cpus = (const CPU[]) { + { + .name = "25", + .cpu_type = CPU_Cx486S, + .fpus = fpus_486sx, + .rspeed = 25000000, + .multi = 1.0, + .voltage = 5000, + .edx_reset = 0x420, + .cpuid_model = 0, + .cyrix_id = 0x0010, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 3 + }, + { + .name = "33", + .cpu_type = CPU_Cx486S, + .fpus = fpus_486sx, + .rspeed = 33333333, + .multi = 1.0, + .voltage = 5000, + .edx_reset = 0x420, + .cpuid_model = 0, + .cyrix_id = 0x0010, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_Cx486S, + .fpus = fpus_486sx, + .rspeed = 40000000, + .multi = 1.0, + .voltage = 5000, + .edx_reset = 0x420, + .cpuid_model = 0, + .cyrix_id = 0x0010, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Cyrix", + .name = "Cx486DX", + .internal_name = "cx486dx", + .cpus = (const CPU[]) { + { + .name = "33", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 33333333, + .multi = 1.0, + .voltage = 5000, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x051a, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 4 + }, + { + .name = "40", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 40000000, + .multi = 1.0, + .voltage = 5000, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x051a, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET1, + .manufacturer = "Cyrix", + .name = "Cx486DX2", + .internal_name = "cx486dx2", + .cpus = (const CPU[]) { + { + .name = "50", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 2.0, + .voltage = 5000, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x081b, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 6 + }, + { + .name = "66", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 2.0, + .voltage = 5000, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x0b1b, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { + .name = "80", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 80000000, + .multi = 2.0, + .voltage = 5000, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x311b, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3, + .manufacturer = "Cyrix", + .name = "Cx486DX4", + .internal_name = "cx486dx4", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0, + .cyrix_id = 0x361f, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 9 + }, + { + .name = "100", + .cpu_type = CPU_Cx486DX, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0, + .cyrix_id = 0x361f, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET3, + .manufacturer = "Cyrix", + .name = "Cx5x86", + .internal_name = "cx5x86", + .cpus = (const CPU[]) { + { /*If we're including the Pentium 50, might as well include this*/ + .name = "80", + .cpu_type = CPU_Cx5x86, + .fpus = fpus_internal, + .rspeed = 80000000, + .multi = 2.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0, + .cyrix_id = 0x002f, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { + .name = "100", + .cpu_type = CPU_Cx5x86, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0, + .cyrix_id = 0x002f, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { + .name = "120", + .cpu_type = CPU_Cx5x86, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 3.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0, + .cyrix_id = 0x002f, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 15 + }, + { + .name = "133", + .cpu_type = CPU_Cx5x86, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 4.0, + .voltage = 5000, + .edx_reset = 0x480, + .cpuid_model = 0, + .cyrix_id = 0x002f, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 16 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_STPC, + .manufacturer = "ST", + .name = "STPC-DX", + .internal_name = "stpc_dx", + .cpus = (const CPU[]) { + { + .name = "66", + .cpu_type = CPU_STPC, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 3300, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x051a, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { + .name = "75", + .cpu_type = CPU_STPC, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 1.0, + .voltage = 3300, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x051a, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 5 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_STPC, + .manufacturer = "ST", + .name = "STPC-DX2", + .internal_name = "stpc_dx2", + .cpus = (const CPU[]) { + { + .name = "133", + .cpu_type = CPU_STPC, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3300, + .edx_reset = 0x430, + .cpuid_model = 0, + .cyrix_id = 0x0b1b, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET4, + .manufacturer = "Intel", + .name = "Pentium", + .internal_name = "pentium_p5", + .cpus = (const CPU[]) { + { + .name = "50 (Q0399)", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 50000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x513, + .cpuid_model = 0x513, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 4, + .mem_write_cycles = 4, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 6 + }, + { + .name = "60", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 60000000, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x517, + .cpuid_model = 0x517, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 7 + }, + { + .name = "66", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1, + .voltage = 5000, + .edx_reset = 0x517, + .cpuid_model = 0x517, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET4, + .manufacturer = "Intel", + .name = "Pentium OverDrive", + .internal_name = "pentium_p54c_od5v", + .cpus = (const CPU[]) { + { + .name = "100", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x51A, + .cpuid_model = 0x51A, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 12 + }, + { + .name = "120", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x51A, + .cpuid_model = 0x51A, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "133", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2, + .voltage = 5000, + .edx_reset = 0x51A, + .cpuid_model = 0x51A, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium", + .internal_name = "pentium_p54c", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x522, + .cpuid_model = 0x522, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 9 + }, + { + .name = "90", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 90000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x524, + .cpuid_model = 0x524, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 21/2 + }, + { + .name = "100/50", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x524, + .cpuid_model = 0x524, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 10, + .mem_write_cycles = 10, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 12 + }, + { + .name = "100/66", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x526, + .cpuid_model = 0x526, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { + .name = "120", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x526, + .cpuid_model = 0x526, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "133", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "150", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "166", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "200", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium MMX", + .internal_name = "pentium_p55c", + .cpus = (const CPU[]) { + { + .name = "166", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2800, + .edx_reset = 0x543, + .cpuid_model = 0x543, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "200", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2800, + .edx_reset = 0x543, + .cpuid_model = 0x543, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "233", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2800, + .edx_reset = 0x543, + .cpuid_model = 0x543, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Mobile Pentium MMX", + .internal_name = "pentium_tillamook", + .cpus = (const CPU[]) { + { + .name = "120", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x543, + .cpuid_model = 0x543, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "133", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x543, + .cpuid_model = 0x543, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "150", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 2800, + .edx_reset = 0x544, + .cpuid_model = 0x544, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "166", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2800, + .edx_reset = 0x544, + .cpuid_model = 0x544, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "200", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2800, + .edx_reset = 0x581, + .cpuid_model = 0x581, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "233", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2800, + .edx_reset = 0x581, + .cpuid_model = 0x581, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { + .name = "266", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2800, + .edx_reset = 0x582, + .cpuid_model = 0x582, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2800, + .edx_reset = 0x582, + .cpuid_model = 0x582, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 36 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium OverDrive", + .internal_name = "pentium_p54c_od3v", + .cpus = (const CPU[]) { + { + .name = "125", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 125000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 15 + }, + { + .name = "150", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "166", + .cpu_type = CPU_PENTIUM, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x52c, + .cpuid_model = 0x52c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Intel", + .name = "Pentium OverDrive MMX", + .internal_name = "pentium_p55c_od", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x1542, + .cpuid_model = 0x1542, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 9 + }, + { + .name = "125", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 125000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x1542, + .cpuid_model = 0x1542, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 15 + }, + { + .name = "150/60", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x1542, + .cpuid_model = 0x1542, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "166", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 166000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x1542, + .cpuid_model = 0x1542, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "180", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 180000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x1542, + .cpuid_model = 0x1542, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 21 + }, + { + .name = "200", + .cpu_type = CPU_PENTIUMMMX, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x1542, + .cpuid_model = 0x1542, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "IDT", + .name = "WinChip", + .internal_name = "winchip", + .cpus = (const CPU[]) { + { + .name = "75", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 9 + }, + { + .name = "90", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 90000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 21/2 + }, + { + .name = "100", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { + .name = "120", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "133", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "150", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "166", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 40 + }, + { + .name = "180", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 180000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 21 + }, + { + .name = "200", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "225", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 225000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 27 + }, + { + .name = "240", + .cpu_type = CPU_WINCHIP, + .fpus = fpus_internal, + .rspeed = 240000000, + .multi = 4.0, + .voltage = 3520, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 28 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "IDT", + .name = "WinChip 2", + .internal_name = "winchip2", + .cpus = (const CPU[]) { + { + .name = "200", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 3*8 + }, + { + .name = "225", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 225000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 3*9 + }, + { + .name = "240", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 240000000, + .multi = 4.0, + .voltage = 3520, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 30 + }, + { + .name = "250", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 250000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 30 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "IDT", + .name = "WinChip 2A", + .internal_name = "winchip2a", + .cpus = (const CPU[]) { + { + .name = "200", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x587, + .cpuid_model = 0x587, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 3*8 + }, + { + .name = "233", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 3520, + .edx_reset = 0x587, + .cpuid_model = 0x587, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = (7*8)/2 + }, + { + .name = "266", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 7.0/3.0, + .voltage = 3520, + .edx_reset = 0x587, + .cpuid_model = 0x587, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 28 + }, + { + .name = "300", + .cpu_type = CPU_WINCHIP2, + .fpus = fpus_internal, + .rspeed = 250000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x587, + .cpuid_model = 0x587, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 8, + .cache_write_cycles = 8, + .atclk_div = 30 + }, + { .name = "", 0 } + } + }, +#ifdef USE_AMD_K5 + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K5 (Model 0)", + .internal_name = "k5_ssa5", + .cpus = (const CPU[]) { + { + .name = "75 (PR75)", + .cpu_type = CPU_K5, + .fpus = fpus_internal, + .rspeed = 75000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x501, + .cpuid_model = 0x501, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 9 + }, + { + .name = "90 (PR90)", + .cpu_type = CPU_K5, + .fpus = fpus_internal, + .rspeed = 90000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x501, + .cpuid_model = 0x501, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 21/2 + }, + { + .name = "100 (PR100)", + .cpu_type = CPU_K5, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 3520, + .edx_reset = 0x501, + .cpuid_model = 0x501, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K5 (Model 1/2/3)", + .internal_name = "k5_5k86", + .cpus = (const CPU[]) { + { + .name = "90 (PR120)", + .cpu_type = CPU_5K86, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x511, + .cpuid_model = 0x511, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "100 (PR133)", + .cpu_type = CPU_5K86, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x514, + .cpuid_model = 0x514, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "105 (PR150)", + .cpu_type = CPU_5K86, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x524, + .cpuid_model = 0x524, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "116.7 (PR166)", + .cpu_type = CPU_5K86, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 3520, + .edx_reset = 0x524, + .cpuid_model = 0x524, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "133 (PR200)", + .cpu_type = CPU_5K86, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3520, + .edx_reset = 0x534, + .cpuid_model = 0x534, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { .name = "", 0 } + } + }, +#endif /* USE_AMD_K5 */ + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6 (Model 6)", + .internal_name = "k6_m6", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "66", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 2900, + .edx_reset = 0x561, + .cpuid_model = 0x561, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2900, + .edx_reset = 0x561, + .cpuid_model = 0x561, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2900, + .edx_reset = 0x561, + .cpuid_model = 0x561, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "166", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2900, + .edx_reset = 0x561, + .cpuid_model = 0x561, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "200", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2900, + .edx_reset = 0x561, + .cpuid_model = 0x561, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "233", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 3200, + .edx_reset = 0x561, + .cpuid_model = 0x561, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_SLOT1, - .manufacturer = "Intel", - .name = "Celeron (Covington)", - .internal_name = "celeron_covington", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 6, 6, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 9, 9, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,12,12, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,15,15, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,18,18, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,21,21, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x650, 0x650, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,24,24, 32}, - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,25,25, 36}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6 (Model 7)", + .internal_name = "k6_m7", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "100", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2200, + .edx_reset = 0x570, + .cpuid_model = 0x570, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2200, + .edx_reset = 0x570, + .cpuid_model = 0x570, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 166666666, .multi = 2.5, + .voltage = 2200, .edx_reset = 0x570, + .cpuid_model = 0x570, .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "200", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 200000000, .multi = 3.0, + .voltage = 2200, .edx_reset = 0x570, + .cpuid_model = 0x570, .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "233", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 233333333, .multi = 3.5, + .voltage = 2200, .edx_reset = 0x570, + .cpuid_model = 0x570, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { + .name = "266", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x570, + .cpuid_model = 0x570, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_K6, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2200, + .edx_reset = 0x570, + .cpuid_model = 0x570, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 36 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-2", + .internal_name = "k6_2", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "100", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "233", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { + .name = "266", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 3.0, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 36 + }, + { + .name = "333", + .cpu_type = CPU_K6_2, + .fpus = fpus_internal, + .rspeed = 332500000, + .multi = 3.5, + .voltage = 2200, + .edx_reset = 0x580, + .cpuid_model = 0x580, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 30, + .mem_write_cycles = 30, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 40 + }, + { + .name = "350", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 350000000, + .multi = 3.5, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 32, + .mem_write_cycles = 32, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 42 + }, + { + .name = "366", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 366666666, + .multi = 5.5, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 33, + .mem_write_cycles = 33, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 44 + }, + { + .name = "380", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 380000000, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 34, + .mem_write_cycles = 34, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 46 + }, + { + .name = "400/66", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 6.0, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "400/100", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "450", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { + .name = "475", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 475000000, + .multi = 5.0, + .voltage = 2400, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 43, + .mem_write_cycles = 43, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 57 + }, + { + .name = "500", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 500000000, + .multi = 5.0, + .voltage = 2400, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 45, + .mem_write_cycles = 45, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 60 + }, + { + .name = "533", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 533333333, + .multi = 5.5, + .voltage = 2200, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 48, + .mem_write_cycles = 48, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 64 + }, + { + .name = "550", + .cpu_type = CPU_K6_2C, + .fpus = fpus_internal, + .rspeed = 550000000, + .multi = 5.5, + .voltage = 2300, + .edx_reset = 0x58c, + .cpuid_model = 0x58c, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 50, + .mem_write_cycles = 50, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 66 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_SLOT2, - .manufacturer = "Intel", - .name = "Pentium II Xeon", - .internal_name = "pentium2_xeon", - .cpus = (const CPU[]) { - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 3, 3, 12}, /* out of spec */ - {"150", CPU_PENTIUM2D, fpus_internal, 150000000, 1.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 14,14, 4, 4, 18}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 2.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 6, 6, 24}, /* out of spec */ - {"250", CPU_PENTIUM2D, fpus_internal, 250000000, 2.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 22,22, 7, 7, 30}, /* out of spec */ - {"300", CPU_PENTIUM2D, fpus_internal, 300000000, 3.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36}, /* out of spec */ - {"350", CPU_PENTIUM2D, fpus_internal, 350000000, 3.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,10,10, 42}, /* out of spec */ - {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 4.0, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48}, - {"450", CPU_PENTIUM2D, fpus_internal, 450000000, 4.5, 2050, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-2+", + .internal_name = "k6_2p", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "100", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { /* out of spec */ + .name = "266", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { /* out of spec */ + .name = "300", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 3.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 36 + }, + { /* out of spec */ + .name = "333", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 332500000, + .multi = 3.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 30, + .mem_write_cycles = 30, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 40 + }, + { /* out of spec */ + .name = "350", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 350000000, + .multi = 3.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 32, + .mem_write_cycles = 32, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 42 + }, + { /* out of spec */ + .name = "366", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 366666666, + .multi = 5.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 33, + .mem_write_cycles = 33, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 44 + }, + { /* out of spec */ + .name = "380", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 380000000, + .multi = 4.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 34, + .mem_write_cycles = 34, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 46 + }, + { /* out of spec */ + .name = "400/66", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 6.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { /* out of spec */ + .name = "400/100", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 4.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "450", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { + .name = "475", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 475000000, + .multi = 5.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 43, + .mem_write_cycles = 43, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 57 + }, + { + .name = "500", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 500000000, + .multi = 5.0, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 45, + .mem_write_cycles = 45, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 60 + }, + { + .name = "533", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 533333333, + .multi = 5.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 48, + .mem_write_cycles = 48, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 64 + }, + { + .name = "550", + .cpu_type = CPU_K6_2P, + .fpus = fpus_internal, + .rspeed = 550000000, + .multi = 5.5, + .voltage = 2000, + .edx_reset = 0x5d4, + .cpuid_model = 0x5d4, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 50, + .mem_write_cycles = 50, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 66 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_SOCKET370, - .manufacturer = "Intel", - .name = "Celeron (Mendocino)", - .internal_name = "celeron_mendocino", - .cpus = (const CPU[]) { - {"66", CPU_PENTIUM2D, fpus_internal, 66666666, 1.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */ - {"100", CPU_PENTIUM2D, fpus_internal, 100000000, 1.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 8, 8, 4, 4, 12}, /* out of spec */ - {"133", CPU_PENTIUM2D, fpus_internal, 133333333, 2.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 11,11, 5, 5, 16}, /* out of spec */ - {"166", CPU_PENTIUM2D, fpus_internal, 166666666, 2.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 14,14, 7, 7, 20}, /* out of spec */ - {"200", CPU_PENTIUM2D, fpus_internal, 200000000, 3.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 17,17, 8, 8, 24}, /* out of spec */ - {"233", CPU_PENTIUM2D, fpus_internal, 233333333, 3.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 19,19, 9, 9, 28}, /* out of spec */ - {"266", CPU_PENTIUM2D, fpus_internal, 266666666, 4.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 22,22,11,11, 32}, /* out of spec */ - {"300A", CPU_PENTIUM2D, fpus_internal, 300000000, 4.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 25,25,12,12, 36}, - {"333", CPU_PENTIUM2D, fpus_internal, 333333333, 5.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 27,27,13,13, 40}, - {"366", CPU_PENTIUM2D, fpus_internal, 366666666, 5.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 33,33,17,17, 44}, - {"400", CPU_PENTIUM2D, fpus_internal, 400000000, 6.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 36,36,12,12, 48}, - {"433", CPU_PENTIUM2D, fpus_internal, 433333333, 6.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 39,39,13,13, 51}, - {"466", CPU_PENTIUM2D, fpus_internal, 466666666, 7.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 42,42,14,14, 56}, - {"500", CPU_PENTIUM2D, fpus_internal, 500000000, 7.5, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 45,45,15,15, 60}, - {"533", CPU_PENTIUM2D, fpus_internal, 533333333, 8.0, 2050, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, 48,48,17,17, 64}, - {"", 0} - } + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-III", + .internal_name = "k6_3", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "100", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { /* out of spec */ + .name = "266", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { /* out of spec */ + .name = "300", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 3.0, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 36 + }, + { /* out of spec */ + .name = "333", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 332500000, + .multi = 3.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 30, + .mem_write_cycles = 30, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 40 + }, + { /* out of spec */ + .name = "350", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 350000000, + .multi = 3.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 32, + .mem_write_cycles = 32, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 42 + }, + { /* out of spec */ + .name = "366", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 366666666, + .multi = 5.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 33, + .mem_write_cycles = 33, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 44 + }, + { /* out of spec */ + .name = "380", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 380000000, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 34, + .mem_write_cycles = 34, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 46 + }, + { + .name = "400", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 4.0, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "450", + .cpu_type = CPU_K6_3, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2200, + .edx_reset = 0x591, + .cpuid_model = 0x591, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "AMD", + .name = "K6-III+", + .internal_name = "k6_3p", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "100", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 7, + .mem_write_cycles = 7, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 9 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { /* out of spec */ + .name = "266", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { /* out of spec */ + .name = "300", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 3.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 36 + }, + { /* out of spec */ + .name = "333", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 332500000, + .multi = 3.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 30, + .mem_write_cycles = 30, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 40 + }, + { /* out of spec */ + .name = "350", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 350000000, + .multi = 3.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 32, + .mem_write_cycles = 32, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 42 + }, + { /* out of spec */ + .name = "366", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 366666666, + .multi = 5.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 33, + .mem_write_cycles = 33, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 44 + }, + { /* out of spec */ + .name = "380", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 380000000, + .multi = 4.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 34, + .mem_write_cycles = 34, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 46 + }, + { + .name = "400", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 4.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "450", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { + .name = "475", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 475000000, + .multi = 5.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 43, + .mem_write_cycles = 43, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 57 + }, + { + .name = "500", + .cpu_type = CPU_K6_3P, + .fpus = fpus_internal, + .rspeed = 500000000, + .multi = 5.0, + .voltage = 2000, + .edx_reset = 0x5d0, + .cpuid_model = 0x5d0, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 45, + .mem_write_cycles = 45, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 60 + }, + { .name = "", 0 } + } + }, +#ifdef USE_CYRIX_6X86 + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "Cx6x86", + .internal_name = "cx6x86", + .cpus = (const CPU[]) { + { + .name = "80 (PR90+)", + .cpu_type = CPU_Cx6x86, + .fpus = fpus_internal, + .rspeed = 80000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x520, + .cpuid_model = 0x520, + .cyrix_id = 0x1731, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 10 + }, + { + .name = "100 (PR120+)", + .cpu_type = CPU_Cx6x86, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x520, + .cpuid_model = 0x520, + .cyrix_id = 0x1731, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 10, + .mem_write_cycles = 10, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 12 + }, + { + .name = "110 (PR133+)", + .cpu_type = CPU_Cx6x86, + .fpus = fpus_internal, + .rspeed = 110000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x520, + .cpuid_model = 0x520, + .cyrix_id = 0x1731, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 10, + .mem_write_cycles = 10, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "120 (PR150+)", + .cpu_type = CPU_Cx6x86, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x520, + .cpuid_model = 0x520, + .cyrix_id = 0x1731, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "133 (PR166+)", + .cpu_type = CPU_Cx6x86, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x520, + .cpuid_model = 0x520, + .cyrix_id = 0x1731, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "150 (PR200+)", + .cpu_type = CPU_Cx6x86, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.0, + .voltage = 3520, + .edx_reset = 0x520, + .cpuid_model = 0x520, + .cyrix_id = 0x1731, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 18 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "Cx6x86L", + .internal_name = "cx6x86l", + .cpus = (const CPU[]) { + { + .name = "110 (PR133+)", + .cpu_type = CPU_Cx6x86L, + .fpus = fpus_internal, + .rspeed = 110000000, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0x2231, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 10, + .mem_write_cycles = 10, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "120 (PR150+)", + .cpu_type = CPU_Cx6x86L, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0x2231, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 14 + }, + { + .name = "133 (PR166+)", + .cpu_type = CPU_Cx6x86L, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0x2231, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "150 (PR200+)", + .cpu_type = CPU_Cx6x86L, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x540, + .cpuid_model = 0x540, + .cyrix_id = 0x2231, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 18 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "Cx6x86MX", + .internal_name = "cx6x86mx", + .cpus = (const CPU[]) { + { + .name = "133 (PR166)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2900, + .edx_reset = 0x600, + .cpuid_model = 0x600, + .cyrix_id = 0x0451, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { + .name = "166 (PR200)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2900, + .edx_reset = 0x600, + .cpuid_model = 0x600, + .cyrix_id = 0x0452, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "187.5 (PR233)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 187500000, + .multi = 2.5, + .voltage = 2900, + .edx_reset = 0x600, + .cpuid_model = 0x600, + .cyrix_id = 0x0452, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 45/2 + }, + { + .name = "208.3 (PR266)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 208333333, + .multi = 2.5, + .voltage = 2700, + .edx_reset = 0x600, + .cpuid_model = 0x600, + .cyrix_id = 0x0452, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 17, + .mem_write_cycles = 17, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 25 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET5_7, + .manufacturer = "Cyrix", + .name = "MII", + .internal_name = "mii", + .cpus = (const CPU[]) { + { + .name = "233 (PR300)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0852, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 28 + }, + { + .name = "250/83 (PR333)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 250000000, + .multi = 3.0, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0853, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 23, + .mem_write_cycles = 23, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 30 + }, + { + .name = "250/100 (PR366)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 250000000, + .multi = 2.5, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0853, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 23, + .mem_write_cycles = 23, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 30 + }, + { + .name = "285 (PR400)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 285000000, + .multi = 3.0, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0853, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 34 + }, + { + .name = "300 (PR433)", + .cpu_type = CPU_Cx6x86MX, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 3.0, + .voltage = 2900, + .edx_reset = 0x601, + .cpuid_model = 0x601, + .cyrix_id = 0x0853, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 36 + }, + { .name = "", 0 } + } + }, +#endif /* USE_CYRIX_6X86 */ + { + .package = CPU_PKG_SOCKET8, + .manufacturer = "Intel", + .name = "Pentium Pro", + .internal_name = "pentiumpro", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "60", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 60000000, + .multi = 1.0, + .voltage = 3100, + .edx_reset = 0x612, + .cpuid_model = 0x612, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 1, + .cache_write_cycles = 1, + .atclk_div = 7 + }, + { /* out of spec */ + .name = "66", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 3300, + .edx_reset = 0x617, + .cpuid_model = 0x617, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 1, + .cache_write_cycles = 1, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "90", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 90000000, + .multi = 1.5, + .voltage = 3100, + .edx_reset = 0x612, + .cpuid_model = 0x612, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 11 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 3300, + .edx_reset = 0x617, + .cpuid_model = 0x617, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "120", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 120000000, + .multi = 2.0, + .voltage = 3100, + .edx_reset = 0x612, + .cpuid_model = 0x612, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 5, + .cache_write_cycles = 5, + .atclk_div = 14 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3300, + .edx_reset = 0x617, + .cpuid_model = 0x617, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 5, + .cache_write_cycles = 5, + .atclk_div = 16 + }, /* out of spec */ + { + .name = "150", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 2.5, + .voltage = 3100, + .edx_reset = 0x612, + .cpuid_model = 0x612, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 35/2 + }, + { + .name = "166", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 3300, + .edx_reset = 0x617, + .cpuid_model = 0x617, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { + .name = "180", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 180000000, + .multi = 3.0, + .voltage = 3300, + .edx_reset = 0x617, + .cpuid_model = 0x617, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 21 + }, + { + .name = "200", + .cpu_type = CPU_PENTIUMPRO, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3300, + .edx_reset = 0x617, + .cpuid_model = 0x617, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET8, + .manufacturer = "Intel", + .name = "Pentium II OverDrive", + .internal_name = "pentium2_od", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "66", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { /* out of spec */ + .name = "266", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 5.0, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 36 + }, + { + .name = "333", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 333333333, + .multi = 5.0, + .voltage = 3300, + .edx_reset = 0x1632, + .cpuid_model = 0x1632, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 40 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SLOT1, + .manufacturer = "Intel", + .name = "Pentium II (Klamath)", + .internal_name = "pentium2_klamath", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "66", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { + .name = "233", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 28 + }, + { + .name = "266", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_PENTIUM2, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2800, + .edx_reset = 0x634, + .cpuid_model = 0x634, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 25, + .mem_write_cycles = 25, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 36 + }, + { .name = "", 0 } + } }, { - .package = CPU_PKG_SOCKET370, - .manufacturer = "VIA", - .name = "Cyrix III", - .internal_name = "c3_samuel", - .cpus = (const CPU[]) { - {"66", CPU_CYRIX3S, fpus_internal, 66666666, 1.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of multiplier range */ - {"100", CPU_CYRIX3S, fpus_internal, 100000000, 1.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of multiplier range */ - {"133", CPU_CYRIX3S, fpus_internal, 133333333, 2.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 12, 12, 6, 6, 16}, /* out of multiplier range */ - {"166", CPU_CYRIX3S, fpus_internal, 166666666, 2.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 15, 15, 7, 7, 20}, /* out of multiplier range */ - {"200", CPU_CYRIX3S, fpus_internal, 200000000, 3.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 18, 18, 8, 8, 24}, /* out of multiplier range */ - {"233", CPU_CYRIX3S, fpus_internal, 233333333, 3.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 21, 21, 9, 9, 28}, /* out of multiplier range */ - {"266", CPU_CYRIX3S, fpus_internal, 266666666, 4.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 24, 24, 12, 12, 32}, /* out of multiplier range */ - {"300", CPU_CYRIX3S, fpus_internal, 300000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 27, 27, 13, 13, 36}, /* out of spec */ - {"333", CPU_CYRIX3S, fpus_internal, 333333333, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 30, 30, 15, 15, 40}, /* out of spec */ - {"366", CPU_CYRIX3S, fpus_internal, 366666666, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 33, 33, 16, 16, 44}, /* out of spec */ - {"400", CPU_CYRIX3S, fpus_internal, 400000000, 6.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48}, - {"433", CPU_CYRIX3S, fpus_internal, 433333333, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 39, 39, 18, 18, 52}, /* out of spec */ - {"450", CPU_CYRIX3S, fpus_internal, 450000000, 4.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 41, 41, 14, 14, 54}, - {"466", CPU_CYRIX3S, fpus_internal, 466666666, 6.5, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 42, 42, 14, 14, 56}, /* out of spec */ - {"500", CPU_CYRIX3S, fpus_internal, 500000000, 5.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 45, 45, 15, 15, 60}, - {"533", CPU_CYRIX3S, fpus_internal, 533333333, 8.0, 2050, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 48, 48, 15, 15, 64}, /* out of spec */ - {"550", CPU_CYRIX3S, fpus_internal, 550000000, 5.5, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 50, 50, 17, 17, 66}, - {"600/100", CPU_CYRIX3S, fpus_internal, 600000000, 6.0, 2050, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72}, - {"600/133", CPU_CYRIX3S, fpus_internal, 600000000, 4.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 13, 13, 72}, - {"650", CPU_CYRIX3S, fpus_internal, 650000000, 6.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 58, 58, 20, 20, 78}, - {"667", CPU_CYRIX3S, fpus_internal, 666666667, 5.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 60, 60, 16, 16, 80}, - {"700", CPU_CYRIX3S, fpus_internal, 700000000, 7.0, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 63, 63, 21, 21, 84}, - {"733", CPU_CYRIX3S, fpus_internal, 733333333, 5.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 66, 66, 18, 18, 88}, - {"", 0} - } + .package = CPU_PKG_SLOT1, + .manufacturer = "Intel", + .name = "Pentium II (Deschutes)", + .internal_name = "pentium2_deschutes", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "66", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 5, + .cache_write_cycles = 5, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 28 + }, + { + .name = "266", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x651, + .cpuid_model = 0x651, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 25, + .mem_write_cycles = 25, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 36 + }, + { + .name = "333", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 333333333, + .multi = 5.0, + .voltage = 2050, + .edx_reset = 0x651, + .cpuid_model = 0x651, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 40 + }, + { + .name = "350", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 350000000, + .multi = 3.5, + .voltage = 2050, + .edx_reset = 0x651, + .cpuid_model = 0x651, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 32, + .mem_write_cycles = 32, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 42 + }, + { + .name = "400", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 4.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "450", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SLOT1, + .manufacturer = "Intel", + .name = "Celeron (Covington)", + .internal_name = "celeron_covington", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "66", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 18, + .cache_write_cycles = 18, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 21, + .cache_write_cycles = 21, + .atclk_div = 28 + }, + { + .name = "266", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2050, + .edx_reset = 0x650, + .cpuid_model = 0x650, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 24, + .cache_write_cycles = 24, + .atclk_div = 32 + }, + { + .name = "300", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x651, + .cpuid_model = 0x651, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 25, + .mem_write_cycles = 25, + .cache_read_cycles = 25, + .cache_write_cycles = 25, + .atclk_div = 36 + }, + { .name = "", 0 } + } }, { - .package = 0, - } + .package = CPU_PKG_SLOT2, + .manufacturer = "Intel", + .name = "Pentium II Xeon", + .internal_name = "pentium2_xeon", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "150", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 150000000, + .multi = 1.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 18 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 2.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "250", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 250000000, + .multi = 2.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 22, + .mem_write_cycles = 22, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 30 + }, + { /* out of spec */ + .name = "300", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 3.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 36 + }, + { /* out of spec */ + .name = "350", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 350000000, + .multi = 3.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 32, + .mem_write_cycles = 32, + .cache_read_cycles = 10, + .cache_write_cycles = 10, + .atclk_div = 42 + }, + { + .name = "400", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 4.0, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "450", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x652, + .cpuid_model = 0x652, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET370, + .manufacturer = "Intel", + .name = "Celeron (Mendocino)", + .internal_name = "celeron_mendocino", + .cpus = (const CPU[]) { + { /* out of spec */ + .name = "66", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { /* out of spec */ + .name = "100", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 8, + .mem_write_cycles = 8, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of spec */ + .name = "133", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 11, + .mem_write_cycles = 11, + .cache_read_cycles = 5, + .cache_write_cycles = 5, + .atclk_div = 16 + }, + { /* out of spec */ + .name = "166", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 14, + .mem_write_cycles = 14, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of spec */ + .name = "200", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 17, + .mem_write_cycles = 17, + .cache_read_cycles = 8, + .cache_write_cycles = 8, + .atclk_div = 24 + }, + { /* out of spec */ + .name = "233", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 19, + .mem_write_cycles = 19, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 28 + }, + { /* out of spec */ + .name = "266", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 22, + .mem_write_cycles = 22, + .cache_read_cycles = 11, + .cache_write_cycles = 11, + .atclk_div = 32 + }, + { + .name = "300A", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 25, + .mem_write_cycles = 25, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 36 + }, + { + .name = "333", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 333333333, + .multi = 5.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 40 + }, + { + .name = "366", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 366666666, + .multi = 5.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 33, + .mem_write_cycles = 33, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 44 + }, + { + .name = "400", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 6.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 48 + }, + { + .name = "433", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 433333333, + .multi = 6.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 39, + .mem_write_cycles = 39, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 51 + }, + { + .name = "466", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 466666666, + .multi = 7.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 42, + .mem_write_cycles = 42, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 56 + }, + { + .name = "500", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 500000000, + .multi = 7.5, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 45, + .mem_write_cycles = 45, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 60 + }, + { + .name = "533", + .cpu_type = CPU_PENTIUM2D, + .fpus = fpus_internal, + .rspeed = 533333333, + .multi = 8.0, + .voltage = 2050, + .edx_reset = 0x665, + .cpuid_model = 0x665, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 48, + .mem_write_cycles = 48, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 64 + }, + { .name = "", 0 } + } + }, + { + .package = CPU_PKG_SOCKET370, + .manufacturer = "VIA", + .name = "Cyrix III", + .internal_name = "c3_samuel", + .cpus = (const CPU[]) { + { /* out of multiplier range */ + .name = "66", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 66666666, + .multi = 1.0, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 6, + .mem_write_cycles = 6, + .cache_read_cycles = 3, + .cache_write_cycles = 3, + .atclk_div = 8 + }, + { /* out of multiplier range */ + .name = "100", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 100000000, + .multi = 1.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 9, + .mem_write_cycles = 9, + .cache_read_cycles = 4, + .cache_write_cycles = 4, + .atclk_div = 12 + }, + { /* out of multiplier range */ + .name = "133", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 133333333, + .multi = 2.0, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 12, + .mem_write_cycles = 12, + .cache_read_cycles = 6, + .cache_write_cycles = 6, + .atclk_div = 16 + }, + { /* out of multiplier range */ + .name = "166", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 166666666, + .multi = 2.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 15, + .mem_write_cycles = 15, + .cache_read_cycles = 7, + .cache_write_cycles = 7, + .atclk_div = 20 + }, + { /* out of multiplier range */ + .name = "200", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 200000000, + .multi = 3.0, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 18, + .mem_write_cycles = 18, + .cache_read_cycles = 8, + .cache_write_cycles = 8, + .atclk_div = 24 + }, + { /* out of multiplier range */ + .name = "233", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 233333333, + .multi = 3.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 21, + .mem_write_cycles = 21, + .cache_read_cycles = 9, + .cache_write_cycles = 9, + .atclk_div = 28 + }, + { /* out of multiplier range */ + .name = "266", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 266666666, + .multi = 4.0, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 24, + .mem_write_cycles = 24, + .cache_read_cycles = 12, + .cache_write_cycles = 12, + .atclk_div = 32 + }, + { /* out of spec */ + .name = "300", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 300000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 27, + .mem_write_cycles = 27, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 36 + }, + { /* out of spec */ + .name = "333", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 333333333, + .multi = 5.0, + .voltage = 2050, + .edx_reset = 0x662, + .cpuid_model = 0x662, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 30, + .mem_write_cycles = 30, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 40 + }, + { /* out of spec */ + .name = "366", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 366666666, + .multi = 5.5, + .voltage = 2050, + .edx_reset = 0x662, + .cpuid_model = 0x662, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 33, + .mem_write_cycles = 33, + .cache_read_cycles = 16, + .cache_write_cycles = 16, + .atclk_div = 44 + }, + { + .name = "400", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 400000000, + .multi = 6.0, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 36, + .mem_write_cycles = 36, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 48 + }, + { /* out of spec */ + .name = "433", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 433333333, + .multi = 6.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 39, + .mem_write_cycles = 39, + .cache_read_cycles = 18, + .cache_write_cycles = 18, + .atclk_div = 52 + }, + { + .name = "450", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 450000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 41, + .mem_write_cycles = 41, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 54 + }, + { /* out of spec */ + .name = "466", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 466666666, + .multi = 6.5, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 42, + .mem_write_cycles = 42, + .cache_read_cycles = 14, + .cache_write_cycles = 14, + .atclk_div = 56 + }, + { + .name = "500", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 500000000, + .multi = 5.0, + .voltage = 2050, + .edx_reset = 0x662, + .cpuid_model = 0x662, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 45, + .mem_write_cycles = 45, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 60 + }, + { /* out of spec */ + .name = "533", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 533333333, + .multi = 8.0, + .voltage = 2050, + .edx_reset = 0x660, + .cpuid_model = 0x660, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 48, + .mem_write_cycles = 48, + .cache_read_cycles = 15, + .cache_write_cycles = 15, + .atclk_div = 64 + }, + { + .name = "550", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 550000000, + .multi = 5.5, + .voltage = 2050, + .edx_reset = 0x662, + .cpuid_model = 0x662, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 50, + .mem_write_cycles = 50, + .cache_read_cycles = 17, + .cache_write_cycles = 17, + .atclk_div = 66 + }, + { + .name = "600/100", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 600000000, + .multi = 6.0, + .voltage = 2050, + .edx_reset = 0x662, + .cpuid_model = 0x662, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 54, + .mem_write_cycles = 54, + .cache_read_cycles = 18, + .cache_write_cycles = 18, + .atclk_div = 72 + }, + { + .name = "600/133", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 600000000, + .multi = 4.5, + .voltage = 2050, + .edx_reset = 0x663, + .cpuid_model = 0x663, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 54, + .mem_write_cycles = 54, + .cache_read_cycles = 13, + .cache_write_cycles = 13, + .atclk_div = 72 + }, + { + .name = "650", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 650000000, + .multi = 6.5, + .voltage = 2050, + .edx_reset = 0x663, + .cpuid_model = 0x663, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 58, + .mem_write_cycles = 58, + .cache_read_cycles = 20, + .cache_write_cycles = 20, + .atclk_div = 78 + }, + { + .name = "667", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 666666667, + .multi = 5.0, + .voltage = 2050, + .edx_reset = 0x663, + .cpuid_model = 0x663, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 60, + .mem_write_cycles = 60, + .cache_read_cycles = 16, + .cache_write_cycles = 16, + .atclk_div = 80 + }, + { + .name = "700", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 700000000, + .multi = 7.0, + .voltage = 2050, + .edx_reset = 0x663, + .cpuid_model = 0x663, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 63, + .mem_write_cycles = 63, + .cache_read_cycles = 21, + .cache_write_cycles = 21, + .atclk_div = 84 + }, + { + .name = "733", + .cpu_type = CPU_CYRIX3S, + .fpus = fpus_internal, + .rspeed = 733333333, + .multi = 5.5, + .voltage = 2050, + .edx_reset = 0x663, + .cpuid_model = 0x663, + .cyrix_id = 0, + .cpu_flags = CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, + .mem_read_cycles = 66, + .mem_write_cycles = 66, + .cache_read_cycles = 18, + .cache_write_cycles = 18, + .atclk_div = 88 + }, + { .name = "", 0 } + } + }, + { .package = 0, 0 } // clang-format on }; diff --git a/src/cpu/softfloat/config.h b/src/cpu/softfloat/config.h deleted file mode 100644 index 9e39c2d29c..0000000000 --- a/src/cpu/softfloat/config.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef EMU_SF_CONFIG_H -#define EMU_SF_CONFIG_H - -#include - -typedef int8_t flag; -typedef uint8_t uint8; -typedef int8_t int8; -typedef uint16_t uint16; -typedef int16_t int16; -typedef uint32_t uint32; -typedef int32_t int32; -typedef uint64_t uint64; -typedef int64_t int64; - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines a type that holds integers -| of _exactly_ the number of bits specified. For instance, for most -| implementation of C, `bits16' and `sbits16' should be `typedef'ed to -| `unsigned short int' and `signed short int' (or `short int'), respectively. -*----------------------------------------------------------------------------*/ -typedef uint8_t bits8; -typedef int8_t sbits8; -typedef uint16_t bits16; -typedef int16_t sbits16; -typedef uint32_t bits32; -typedef int32_t sbits32; -typedef uint64_t bits64; -typedef int64_t sbits64; - -typedef uint8_t Bit8u; -typedef int8_t Bit8s; -typedef uint16_t Bit16u; -typedef int16_t Bit16s; -typedef uint32_t Bit32u; -typedef int32_t Bit32s; -typedef uint64_t Bit64u; -typedef int64_t Bit64s; - -/*---------------------------------------------------------------------------- -| The `LIT64' macro takes as its argument a textual integer literal and -| if necessary ``marks'' the literal as having a 64-bit integer type. -| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be -| appended with the letters `LL' standing for `long long', which is `gcc's -| name for the 64-bit integer type. Some compilers may allow `LIT64' to be -| defined as the identity macro: `#define LIT64( a ) a'. -*----------------------------------------------------------------------------*/ -#define BX_CONST64(a) a##LL -#define BX_CPP_INLINE static __inline - -#endif /*EMU_SF_CONFIG_H*/ diff --git a/src/cpu/softfloat/softfloat-compare.h b/src/cpu/softfloat/softfloat-compare.h deleted file mode 100644 index 8b9821460b..0000000000 --- a/src/cpu/softfloat/softfloat-compare.h +++ /dev/null @@ -1,496 +0,0 @@ -/*============================================================================ -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_COMPARE_H_ -#define _SOFTFLOAT_COMPARE_H_ - -#include "softfloat.h" - -// ======= float32 ======= // - -typedef int (*float32_compare_method)(float32, float32, struct float_status_t *status); - -// 0x00 -BX_CPP_INLINE int float32_eq_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_equal); -} - -// 0x01 -BX_CPP_INLINE int float32_lt_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_less); -} - -// 0x02 -BX_CPP_INLINE int float32_le_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x03 -BX_CPP_INLINE int float32_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x04 -BX_CPP_INLINE int float32_neq_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_equal); -} - -// 0x05 -BX_CPP_INLINE int float32_nlt_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_less); -} - -// 0x06 -BX_CPP_INLINE int float32_nle_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x07 -BX_CPP_INLINE int float32_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x08 -BX_CPP_INLINE int float32_eq_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x09 -BX_CPP_INLINE int float32_nge_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x0a -BX_CPP_INLINE int float32_ngt_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_greater); -} - -// 0x0b -BX_CPP_INLINE int float32_false_quiet(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_quiet(a, b, status); - return 0; -} - -// 0x0c -BX_CPP_INLINE int float32_neq_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x0d -BX_CPP_INLINE int float32_ge_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x0e -BX_CPP_INLINE int float32_gt_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_greater); -} - -// 0x0f -BX_CPP_INLINE int float32_true_quiet(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_quiet(a, b, status); - return 1; -} - -// 0x10 -BX_CPP_INLINE int float32_eq_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_equal); -} - -// 0x11 -BX_CPP_INLINE int float32_lt_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_less); -} - -// 0x12 -BX_CPP_INLINE int float32_le_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x13 -BX_CPP_INLINE int float32_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x14 -BX_CPP_INLINE int float32_neq_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_equal); -} - -// 0x15 -BX_CPP_INLINE int float32_nlt_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_less); -} - -// 0x16 -BX_CPP_INLINE int float32_nle_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x17 -BX_CPP_INLINE int float32_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x18 -BX_CPP_INLINE int float32_eq_unordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x19 -BX_CPP_INLINE int float32_nge_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x1a -BX_CPP_INLINE int float32_ngt_unordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation != float_relation_greater); -} - -// 0x1b -BX_CPP_INLINE int float32_false_signalling(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_two(a, b, status); - return 0; -} - -// 0x1c -BX_CPP_INLINE int float32_neq_ordered_signalling(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_two(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x1d -BX_CPP_INLINE int float32_ge_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x1e -BX_CPP_INLINE int float32_gt_ordered_quiet(float32 a, float32 b, struct float_status_t *status) -{ - int relation = float32_compare_quiet(a, b, status); - return (relation == float_relation_greater); -} - -// 0x1f -BX_CPP_INLINE int float32_true_signalling(float32 a, float32 b, struct float_status_t *status) -{ - float32_compare_two(a, b, status); - return 1; -} - -// ======= float64 ======= // - -typedef int (*float64_compare_method)(float64, float64, struct float_status_t *status); - -// 0x00 -BX_CPP_INLINE int float64_eq_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_equal); -} - -// 0x01 -BX_CPP_INLINE int float64_lt_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_less); -} - -// 0x02 -BX_CPP_INLINE int float64_le_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x03 -BX_CPP_INLINE int float64_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x04 -BX_CPP_INLINE int float64_neq_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_equal); -} - -// 0x05 -BX_CPP_INLINE int float64_nlt_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_less); -} - -// 0x06 -BX_CPP_INLINE int float64_nle_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x07 -BX_CPP_INLINE int float64_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x08 -BX_CPP_INLINE int float64_eq_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x09 -BX_CPP_INLINE int float64_nge_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x0a -BX_CPP_INLINE int float64_ngt_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_greater); -} - -// 0x0b -BX_CPP_INLINE int float64_false_quiet(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_quiet(a, b, status); - return 0; -} - -// 0x0c -BX_CPP_INLINE int float64_neq_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x0d -BX_CPP_INLINE int float64_ge_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x0e -BX_CPP_INLINE int float64_gt_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_greater); -} - -// 0x0f -BX_CPP_INLINE int float64_true_quiet(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_quiet(a, b, status); - return 1; -} - -// 0x10 -BX_CPP_INLINE int float64_eq_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_equal); -} - -// 0x11 -BX_CPP_INLINE int float64_lt_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_less); -} - -// 0x12 -BX_CPP_INLINE int float64_le_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_equal); -} - -// 0x13 -BX_CPP_INLINE int float64_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_unordered); -} - -// 0x14 -BX_CPP_INLINE int float64_neq_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_equal); -} - -// 0x15 -BX_CPP_INLINE int float64_nlt_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_less); -} - -// 0x16 -BX_CPP_INLINE int float64_nle_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_less) && (relation != float_relation_equal); -} - -// 0x17 -BX_CPP_INLINE int float64_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_unordered); -} - -// 0x18 -BX_CPP_INLINE int float64_eq_unordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation == float_relation_equal) || (relation == float_relation_unordered); -} - -// 0x19 -BX_CPP_INLINE int float64_nge_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_less) || (relation == float_relation_unordered); -} - -// 0x1a -BX_CPP_INLINE int float64_ngt_unordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation != float_relation_greater); -} - -// 0x1b -BX_CPP_INLINE int float64_false_signalling(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_two(a, b, status); - return 0; -} - -// 0x1c -BX_CPP_INLINE int float64_neq_ordered_signalling(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_two(a, b, status); - return (relation != float_relation_equal) && (relation != float_relation_unordered); -} - -// 0x1d -BX_CPP_INLINE int float64_ge_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_greater) || (relation == float_relation_equal); -} - -// 0x1e -BX_CPP_INLINE int float64_gt_ordered_quiet(float64 a, float64 b, struct float_status_t *status) -{ - int relation = float64_compare_quiet(a, b, status); - return (relation == float_relation_greater); -} - -// 0x1f -BX_CPP_INLINE int float64_true_signalling(float64 a, float64 b, struct float_status_t *status) -{ - float64_compare_two(a, b, status); - return 1; -} - -#endif diff --git a/src/cpu/softfloat/softfloat-macros.h b/src/cpu/softfloat/softfloat-macros.h deleted file mode 100644 index cb867bf5d1..0000000000 --- a/src/cpu/softfloat/softfloat-macros.h +++ /dev/null @@ -1,686 +0,0 @@ -/*============================================================================ -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_MACROS_H_ -#define _SOFTFLOAT_MACROS_H_ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 16, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16u shift16RightJamming(Bit16u a, int count) -{ - Bit16u z; - - if (count == 0) { - z = a; - } - else if (count < 16) { - z = (a>>count) | ((a<<((-count) & 15)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32u shift32RightJamming(Bit32u a, int count) -{ - Bit32u z; - - if (count == 0) { - z = a; - } - else if (count < 32) { - z = (a>>count) | ((a<<((-count) & 31)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u shift64RightJamming(Bit64u a, int count) -{ - Bit64u z; - - if (count == 0) { - z = a; - } - else if (count < 64) { - z = (a>>count) | ((a << ((-count) & 63)) != 0); - } - else { - z = (a != 0); - } - - return z; -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count; - } - else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } - else { - z1 = ((a0 | a1) != 0); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + (z1 < a1); -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void - sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - (a1 < b1); -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit32u aHigh, aLow, bHigh, bLow; - Bit64u z0, zMiddleA, zMiddleB, z1; - - aLow = (Bit32u) a; - aHigh = (Bit32u)(a>>32); - bLow = (Bit32u) b; - bHigh = (Bit32u)(b>>32); - z1 = ((Bit64u) aLow) * bLow; - zMiddleA = ((Bit64u) aLow) * bHigh; - zMiddleB = ((Bit64u) aHigh) * bLow; - z0 = ((Bit64u) aHigh) * bHigh; - zMiddleA += zMiddleB; - z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += (z1 < zMiddleA); - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -#ifdef USE_estimateDiv128To64 -static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b) -{ - Bit64u b0, b1; - Bit64u rem0, rem1, term0, term1; - Bit64u z; - - if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); - b0 = b>>32; - z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; - mul64To128(b, z, &term0, &term1); - sub128(a0, a1, term0, term1, &rem0, &rem1); - while (((Bit64s) rem0) < 0) { - z -= BX_CONST64(0x100000000); - b1 = b<<32; - add128(rem0, rem1, b0, b1, &rem0, &rem1); - } - rem0 = (rem0<<32) | (rem1>>32); - z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; - return z; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -#ifdef USE_estimateSqrt32 -static Bit32u estimateSqrt32(Bit16s aExp, Bit32u a) -{ - static const Bit16u sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const Bit16u sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - Bit32u z; - - int index = (a>>27) & 15; - if (aExp & 1) { - z = 0x4000 + (a>>17) - sqrtOddAdjustments[index]; - z = ((a / z)<<14) + (z<<15); - a >>= 1; - } - else { - z = 0x8000 + (a>>17) - sqrtEvenAdjustments[index]; - z = a / z + z; - z = (0x20000 <= z) ? 0xFFFF8000 : (z<<15); - if (z <= a) return (Bit32u) (((Bit32s) a)>>1); - } - return ((Bit32u) ((((Bit64u) a)<<31) / z)) + (z>>1); -} -#endif - -static const int countLeadingZeros8[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 16 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros16(Bit16u a) -{ - int shiftCount = 0; - if (a < 0x100) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZeros8[a>>8]; - return shiftCount; -} - -#endif - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros32(Bit32u a) -{ - int shiftCount = 0; - if (a < 0x10000) { - shiftCount += 16; - a <<= 16; - } - if (a < 0x1000000) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZeros8[a>>24]; - return shiftCount; -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int countLeadingZeros64(Bit64u a) -{ - int shiftCount = 0; - if (a < BX_CONST64(0x100000000)) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32((Bit32u)(a)); - return shiftCount; -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count); - z0 = a0>>count; - } - else { - z1 = (count < 128) ? (a0>>(count & 63)) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128RightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr) -{ - Bit64u z0, z1; - int negCount = (-count) & 63; - - if (count == 0) { - z1 = a1; - z0 = a0; - } - else if (count < 64) { - z1 = (a0<>count) | ((a1<>count; - } - else { - if (count == 64) { - z1 = a0 | (a1 != 0); - } - else if (count < 128) { - z1 = (a0>>(count & 63)) | (((a0<>((-count) & 63)); -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void add192( - Bit64u a0, - Bit64u a1, - Bit64u a2, - Bit64u b0, - Bit64u b1, - Bit64u b2, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - unsigned carry0, carry1; - - z2 = a2 + b2; - carry1 = (z2 < a2); - z1 = a1 + b1; - carry0 = (z1 < a1); - z0 = a0 + b0; - z1 += carry1; - z0 += (z1 < carry1); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void sub192( - Bit64u a0, - Bit64u a1, - Bit64u a2, - Bit64u b0, - Bit64u b1, - Bit64u b2, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - unsigned borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = (a2 < b2); - z1 = a1 - b1; - borrow0 = (a1 < b1); - z0 = a0 - b0; - z0 -= (z1 < borrow1); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int eq128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 == b0) && (a1 == b1); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int le128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 < b0) || ((a0 == b0) && (a1 <= b1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int lt128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1) -{ - return (a0 < b0) || ((a0 == b0) && (a1 < b1)); -} - -#endif /* FLOATX80 */ - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul128By64To192( - Bit64u a0, - Bit64u a1, - Bit64u b, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2, more1; - - mul64To128(a1, b, &z1, &z2); - mul64To128(a0, b, &z0, &more1); - add128(z0, more1, 0, z1, &z0, &z1); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void mul128To256( - Bit64u a0, - Bit64u a1, - Bit64u b0, - Bit64u b1, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr, - Bit64u *z3Ptr -) -{ - Bit64u z0, z1, z2, z3; - Bit64u more1, more2; - - mul64To128(a1, b1, &z2, &z3); - mul64To128(a1, b0, &z1, &more2); - add128(z1, more2, 0, z2, &z1, &z2); - mul64To128(a0, b0, &z0, &more1); - add128(z0, more1, 0, z1, &z0, &z1); - mul64To128(a0, b1, &more1, &more2); - add128(more1, more2, 0, z2, &more1, &z2); - add128(z0, z1, 0, more1, &z0, &z1); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right -| by 64 _plus_ the number of bits given in `count'. The shifted result is -| at most 128 nonzero bits; these are broken into two 64-bit pieces which are -| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted -| off form a third 64-bit result as follows: The _last_ bit shifted off is -| the most-significant bit of the extra result, and the other 63 bits of the -| extra result are all zero if and only if _all_but_the_last_ bits shifted off -| were all zero. This extra result is stored in the location pointed to by -| `z2Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0', `a1', and `a2' are considered -| to form a fixed-point value with binary point between `a1' and `a2'. This -| fixed-point value is shifted right by the number of bits given in `count', -| and the integer part of the result is returned at the locations pointed to -| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly -| corrupted as described above, and is returned at the location pointed to by -| `z2Ptr'.) -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void shift128ExtraRightJamming( - Bit64u a0, - Bit64u a1, - Bit64u a2, - int count, - Bit64u *z0Ptr, - Bit64u *z1Ptr, - Bit64u *z2Ptr -) -{ - Bit64u z0, z1, z2; - int negCount = (-count) & 63; - - if (count == 0) { - z2 = a2; - z1 = a1; - z0 = a0; - } - else { - if (count < 64) { - z2 = a1<>count); - z0 = a0>>count; - } - else { - if (count == 64) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if (count < 128) { - z2 = a0<>(count & 63); - } - else { - z2 = (count == 128) ? a0 : (a0 != 0); - z1 = 0; - } - } - z0 = 0; - } - z2 |= (a2 != 0); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; -} - -#endif /* FLOAT128 */ - -#endif diff --git a/src/cpu/softfloat/softfloat-muladd.cc b/src/cpu/softfloat/softfloat-muladd.cc deleted file mode 100644 index 7c9fec70ed..0000000000 --- a/src/cpu/softfloat/softfloat-muladd.cc +++ /dev/null @@ -1,558 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * This code is based on QEMU patch by Peter Maydell - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Takes three single-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32MulAddNaN(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - int aIsNaN = float32_is_nan(a); - int bIsNaN = float32_is_nan(b); - - int aIsSignalingNaN = float32_is_signaling_nan(a); - int bIsSignalingNaN = float32_is_signaling_nan(b); - int cIsSignalingNaN = float32_is_signaling_nan(c); - - a |= 0x00400000; - b |= 0x00400000; - c |= 0x00400000; - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) - float_raise(status, float_flag_invalid); - - // operate according to float_first_operand_nan mode - if (aIsSignalingNaN | aIsNaN) { - return a; - } - else { - return (bIsSignalingNaN | bIsNaN) ? b : c; - } -} - -/*---------------------------------------------------------------------------- -| Takes three double-precision floating-point values `a', `b' and `c', one of -| which is a NaN, and returns the appropriate NaN result. If any of `a', -| `b' or `c' is a signaling NaN, the invalid exception is raised. -| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case -| obviously c is a NaN, and whether to propagate c or some other NaN is -| implementation defined). -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64MulAddNaN(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - int aIsNaN = float64_is_nan(a); - int bIsNaN = float64_is_nan(b); - - int aIsSignalingNaN = float64_is_signaling_nan(a); - int bIsSignalingNaN = float64_is_signaling_nan(b); - int cIsSignalingNaN = float64_is_signaling_nan(c); - - a |= BX_CONST64(0x0008000000000000); - b |= BX_CONST64(0x0008000000000000); - c |= BX_CONST64(0x0008000000000000); - - if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN) - float_raise(status, float_flag_invalid); - - // operate according to float_first_operand_nan mode - if (aIsSignalingNaN | aIsNaN) { - return a; - } - else { - return (bIsSignalingNaN | bIsNaN) ? b : c; - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float32 float32_muladd(float32 a, float32 b, float32 c, int flags, struct float_status_t *status) -{ - int aSign, bSign, cSign, zSign; - Bit16s aExp, bExp, cExp, pExp, zExp; - Bit32u aSig, bSig, cSig; - int pInf, pZero, pSign; - Bit64u pSig64, cSig64, zSig64; - Bit32u pSig; - int shiftcount; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - cSig = extractFloat32Frac(c); - cExp = extractFloat32Exp(c); - cSign = extractFloat32Sign(c); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0xff) && aSig) || - ((bExp == 0xff) && bSig) || - ((cExp == 0xff) && cSig)) { - return propagateFloat32MulAddNaN(a, b, c, status); - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - if (cExp == 0) cSig = 0; - } - - int infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) || - (aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0)); - - if (infzero) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0xff) || (bExp == 0xff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0xff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - /* Otherwise generate an infinity of the same sign */ - if ((aSig && aExp == 0) || (bSig && bExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat32(cSign, 0xff, 0); - } - - if (pInf) { - if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat32(pSign, 0xff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (get_float_rounding_mode(status) == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat32(zSign, 0, 0); - } - /* Exact zero plus a denormal */ - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat32(cSign, 0, 0); - } - } - /* Zero plus something non-zero */ - return packFloat32(cSign, cExp, cSig); - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x7e where float32_mul() subtracts 0x7f - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat32() takes. - */ - pExp = aExp + bExp - 0x7e; - aSig = (aSig | 0x00800000) << 7; - bSig = (bSig | 0x00800000) << 8; - pSig64 = (Bit64u)aSig * bSig; - if ((Bit64s)(pSig64 << 1) >= 0) { - pSig64 <<= 1; - pExp--; - } - - zSign = pSign; - - /* Now pSig64 is the significand of the multiply, with the explicit bit in - * position 62. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - pSig = (Bit32u) shift64RightJamming(pSig64, 32); - return roundAndPackFloat32(zSign, pExp - 1, pSig, status); - } - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(cSig, &cExp, &cSig); - } - - cSig64 = (Bit64u)cSig << 39; - cSig64 |= BX_CONST64(0x4000000000000000); - int expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - cSig64 = shift64RightJamming(cSig64, expDiff); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - pSig64 = shift64RightJamming(pSig64, -expDiff); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 62 */ - zSig64 = pSig64 + cSig64; - if ((Bit64s)zSig64 < 0) { - zSig64 = shift64RightJamming(zSig64, 1); - } else { - zExp--; - } - zSig64 = shift64RightJamming(zSig64, 32); - return roundAndPackFloat32(zSign, zExp, zSig64, status); - } else { - /* Subtraction */ - if (expDiff > 0) { - cSig64 = shift64RightJamming(cSig64, expDiff); - zSig64 = pSig64 - cSig64; - zExp = pExp; - } else if (expDiff < 0) { - pSig64 = shift64RightJamming(pSig64, -expDiff); - zSig64 = cSig64 - pSig64; - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (cSig64 < pSig64) { - zSig64 = pSig64 - cSig64; - } else if (pSig64 < cSig64) { - zSig64 = cSig64 - pSig64; - zSign ^= 1; - } else { - /* Exact zero */ - return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0); - } - } - --zExp; - /* Do the equivalent of normalizeRoundAndPackFloat32() but - * starting with the significand in a Bit64u. - */ - shiftcount = countLeadingZeros64(zSig64) - 1; - zSig64 <<= shiftcount; - zExp -= shiftcount; - zSig64 = shift64RightJamming(zSig64, 32); - return roundAndPackFloat32(zSign, zExp, zSig64, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b' then adding 'c', with no intermediate rounding step after the -| multiplication. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic 754-2008. -| The flags argument allows the caller to select negation of the -| addend, the intermediate product, or the final result. (The difference -| between this and having the caller do a separate negation is that negating -| externally will flip the sign bit on NaNs.) -*----------------------------------------------------------------------------*/ - -float64 float64_muladd(float64 a, float64 b, float64 c, int flags, struct float_status_t *status) -{ - int aSign, bSign, cSign, zSign; - Bit16s aExp, bExp, cExp, pExp, zExp; - Bit64u aSig, bSig, cSig; - int pInf, pZero, pSign; - Bit64u pSig0, pSig1, cSig0, cSig1, zSig0, zSig1; - int shiftcount; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - cSig = extractFloat64Frac(c); - cExp = extractFloat64Exp(c); - cSign = extractFloat64Sign(c); - - /* It is implementation-defined whether the cases of (0,inf,qnan) - * and (inf,0,qnan) raise InvalidOperation or not (and what QNaN - * they return if they do), so we have to hand this information - * off to the target-specific pick-a-NaN routine. - */ - if (((aExp == 0x7ff) && aSig) || - ((bExp == 0x7ff) && bSig) || - ((cExp == 0x7ff) && cSig)) { - return propagateFloat64MulAddNaN(a, b, c, status); - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - if (cExp == 0) cSig = 0; - } - - int infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) || - (aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0)); - - if (infzero) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - if (flags & float_muladd_negate_c) { - cSign ^= 1; - } - - /* Work out the sign and type of the product */ - pSign = aSign ^ bSign; - if (flags & float_muladd_negate_product) { - pSign ^= 1; - } - pInf = (aExp == 0x7ff) || (bExp == 0x7ff); - pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0); - - if (cExp == 0x7ff) { - if (pInf && (pSign ^ cSign)) { - /* addition of opposite-signed infinities => InvalidOperation */ - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - /* Otherwise generate an infinity of the same sign */ - if ((aSig && aExp == 0) || (bSig && bExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat64(cSign, 0x7ff, 0); - } - - if (pInf) { - if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) { - float_raise(status, float_flag_denormal); - } - return packFloat64(pSign, 0x7ff, 0); - } - - if (pZero) { - if (cExp == 0) { - if (cSig == 0) { - /* Adding two exact zeroes */ - if (pSign == cSign) { - zSign = pSign; - } else if (get_float_rounding_mode(status) == float_round_down) { - zSign = 1; - } else { - zSign = 0; - } - return packFloat64(zSign, 0, 0); - } - /* Exact zero plus a denormal */ - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat64(cSign, 0, 0); - } - } - /* Zero plus something non-zero */ - return packFloat64(cSign, cExp, cSig); - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - - /* Calculate the actual result a * b + c */ - - /* Multiply first; this is easy. */ - /* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff - * because we want the true exponent, not the "one-less-than" - * flavour that roundAndPackFloat64() takes. - */ - pExp = aExp + bExp - 0x3fe; - aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; - bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; - mul64To128(aSig, bSig, &pSig0, &pSig1); - if ((Bit64s)(pSig0 << 1) >= 0) { - shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1); - pExp--; - } - - zSign = pSign; - - /* Now [pSig0:pSig1] is the significand of the multiply, with the explicit - * bit in position 126. - */ - if (cExp == 0) { - if (!cSig) { - /* Throw out the special case of c being an exact zero now */ - shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1); - return roundAndPackFloat64(zSign, pExp - 1, pSig1, status); - } - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(cSig, &cExp, &cSig); - } - - cSig0 = cSig << 10; - cSig1 = 0; - cSig0 |= BX_CONST64(0x4000000000000000); - int expDiff = pExp - cExp; - - if (pSign == cSign) { - /* Addition */ - if (expDiff > 0) { - /* scale c to match p */ - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - zExp = pExp; - } else if (expDiff < 0) { - /* scale p to match c */ - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - zExp = cExp; - } else { - /* no scaling needed */ - zExp = cExp; - } - /* Add significands and make sure explicit bit ends up in posn 126 */ - add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - if ((Bit64s)zSig0 < 0) { - shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - } else { - zExp--; - } - shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1); - return roundAndPackFloat64(zSign, zExp, zSig1, status); - } else { - /* Subtraction */ - if (expDiff > 0) { - shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1); - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - zExp = pExp; - } else if (expDiff < 0) { - shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1); - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zExp = cExp; - zSign ^= 1; - } else { - zExp = pExp; - if (lt128(cSig0, cSig1, pSig0, pSig1)) { - sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1); - } else if (lt128(pSig0, pSig1, cSig0, cSig1)) { - sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1); - zSign ^= 1; - } else { - /* Exact zero */ - return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0); - } - } - --zExp; - /* Do the equivalent of normalizeRoundAndPackFloat64() but - * starting with the significand in a pair of Bit64u. - */ - if (zSig0) { - shiftcount = countLeadingZeros64(zSig0) - 1; - shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1); - if (zSig1) { - zSig0 |= 1; - } - zExp -= shiftcount; - } else { - shiftcount = countLeadingZeros64(zSig1) - 1; - zSig0 = zSig1 << shiftcount; - zExp -= (shiftcount + 64); - } - return roundAndPackFloat64(zSign, zExp, zSig0, status); - } -} diff --git a/src/cpu/softfloat/softfloat-round-pack.cc b/src/cpu/softfloat/softfloat-round-pack.cc deleted file mode 100644 index 2b3965840c..0000000000 --- a/src/cpu/softfloat/softfloat-round-pack.cc +++ /dev/null @@ -1,896 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s roundAndPackInt32(int zSign, Bit64u exactAbsZ, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - int roundNearestEven = (roundingMode == float_round_nearest_even); - int roundIncrement = 0x40; - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) roundIncrement = 0; - else { - roundIncrement = 0x7F; - if (zSign) { - if (roundingMode == float_round_up) roundIncrement = 0; - } - else { - if (roundingMode == float_round_down) roundIncrement = 0; - } - } - } - int roundBits = (int)(exactAbsZ & 0x7F); - Bit64u absZ = (exactAbsZ + roundIncrement)>>7; - absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - Bit32s z = (Bit32s) absZ; - if (zSign) z = -z; - if ((absZ>>32) || (z && ((z < 0) ^ zSign))) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if (roundBits) { - float_raise(status, float_flag_inexact); - if ((absZ << 7) > exactAbsZ) - set_float_rounding_up(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status) -{ - Bit64s z; - int roundingMode = get_float_rounding_mode(status); - int roundNearestEven = (roundingMode == float_round_nearest_even); - int increment = ((Bit64s) absZ1 < 0); - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) increment = 0; - else { - if (zSign) { - increment = (roundingMode == float_round_down) && absZ1; - } - else { - increment = (roundingMode == float_round_up) && absZ1; - } - } - } - Bit64u exactAbsZ0 = absZ0; - if (increment) { - ++absZ0; - if (absZ0 == 0) goto overflow; - absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven); - } - z = absZ0; - if (zSign) z = -z; - if (z && ((z < 0) ^ zSign)) { - overflow: - float_raise(status, float_flag_invalid); - return (Bit64s)(int64_indefinite); - } - if (absZ1) { - float_raise(status, float_flag_inexact); - if (absZ0 > exactAbsZ0) - set_float_rounding_up(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit unsigned integer corresponding to the -| input. Ordinarily, the fixed-point input is simply rounded to an integer, -| with the inexact exception raised if the input cannot be represented exactly -| as an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - int roundNearestEven = (roundingMode == float_round_nearest_even); - int increment = ((Bit64s) absZ1 < 0); - if (!roundNearestEven) { - if (roundingMode == float_round_to_zero) { - increment = 0; - } else if (absZ1) { - if (zSign) { - increment = (roundingMode == float_round_down) && absZ1; - } else { - increment = (roundingMode == float_round_up) && absZ1; - } - } - } - if (increment) { - ++absZ0; - if (absZ0 == 0) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven); - } - - if (zSign && absZ0) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - if (absZ1) { - float_raise(status, float_flag_inexact); - } - return absZ0; -} - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal half-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr) -{ - int shiftCount = countLeadingZeros16(aSig) - 5; - *zSigPtr = aSig<> 4; - zSigRound &= ~(((roundBits ^ 0x10) == 0) & roundNearestEven); - if (zSigRound == 0) zExp = 0; - return packFloat16(zSign, zExp, zSigRound); -} - -#endif - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr) -{ - int shiftCount = countLeadingZeros32(aSig) - 8; - *zSigPtr = aSig<> 7; - zSigRound &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); - if (zSigRound == 0) zExp = 0; - if (roundBits) { - float_raise(status, float_flag_inexact); - if ((zSigRound << 7) > zSig) set_float_rounding_up(status); - } - return packFloat32(zSign, zExp, zSigRound); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status) -{ - int shiftCount = countLeadingZeros32(zSig) - 1; - return roundAndPackFloat32(zSign, zExp - shiftCount, zSig<>10; - zSigRound &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven); - if (zSigRound == 0) zExp = 0; - if (roundBits) { - float_raise(status, float_flag_inexact); - if ((zSigRound << 10) > zSig) set_float_rounding_up(status); - } - return packFloat64(zSign, zExp, zSigRound); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status) -{ - int shiftCount = countLeadingZeros64(zSig) - 1; - return roundAndPackFloat64(zSign, zExp - shiftCount, zSig< zSigExact) set_float_rounding_up(status); - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (roundBits) float_raise(status, float_flag_inexact); - zSigExact = zSig0; - zSig0 += roundIncrement; - if (zSig0 < roundIncrement) { - // Basically scale by shifting right and keep overflow - ++zExp; - zSig0 = BX_CONST64(0x8000000000000000); - zSigExact >>= 1; // must scale also, or else later tests will fail - } - roundIncrement = roundMask + 1; - if (roundNearestEven && (roundBits<<1 == roundIncrement)) - roundMask |= roundIncrement; - zSig0 &= ~roundMask; - if (zSig0 > zSigExact) set_float_rounding_up(status); - if (zSig0 == 0) zExp = 0; - return packFloatx80(zSign, zExp, zSig0); - precision80: - increment = ((Bit64s) zSig1 < 0); - if (! roundNearestEven) { - if (roundingMode == float_round_to_zero) increment = 0; - else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } - else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - } - if (0x7FFD <= (Bit32u) (zExp - 1)) { - if ((0x7FFE < zExp) - || ((zExp == 0x7FFE) - && (zSig0 == BX_CONST64(0xFFFFFFFFFFFFFFFF)) - && increment)) - { - roundMask = 0; - overflow: - float_raise(status, float_flag_overflow | float_flag_inexact); - if ((roundingMode == float_round_to_zero) - || (zSign && (roundingMode == float_round_up)) - || (! zSign && (roundingMode == float_round_down))) - { - return packFloatx80(zSign, 0x7FFE, ~roundMask); - } - set_float_rounding_up(status); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (zExp <= 0) { - int isTiny = (zExp < 0) || (! increment) - || (zSig0 < BX_CONST64(0xFFFFFFFFFFFFFFFF)); - shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1); - zExp = 0; - if (isTiny) { - if (zSig1 || (zSig0 && !float_exception_masked(status, float_flag_underflow))) - float_raise(status, float_flag_underflow); - } - if (zSig1) float_raise(status, float_flag_inexact); - if (roundNearestEven) increment = ((Bit64s) zSig1 < 0); - else { - if (zSign) { - increment = (roundingMode == float_round_down) && zSig1; - } else { - increment = (roundingMode == float_round_up) && zSig1; - } - } - if (increment) { - zSigExact = zSig0++; - zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); - if (zSig0 > zSigExact) set_float_rounding_up(status); - if ((Bit64s) zSig0 < 0) zExp = 1; - } - return packFloatx80(zSign, zExp, zSig0); - } - } - if (zSig1) float_raise(status, float_flag_inexact); - if (increment) { - zSigExact = zSig0++; - if (zSig0 == 0) { - zExp++; - zSig0 = BX_CONST64(0x8000000000000000); - zSigExact >>= 1; // must scale also, or else later tests will fail - } - else { - zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven); - } - if (zSig0 > zSigExact) set_float_rounding_up(status); - } - else { - if (zSig0 == 0) zExp = 0; - } - return packFloatx80(zSign, zExp, zSig0); -} - -floatx80 roundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) -{ - struct float_status_t *round_status = status; - floatx80 result = SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); - - // bias unmasked undeflow - if (status->float_exception_flags & ~status->float_exception_masks & float_flag_underflow) { - float_raise(round_status, float_flag_underflow); - return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp + 0x6000, zSig0, zSig1, status = round_status); - } - - // bias unmasked overflow - if (status->float_exception_flags & ~status->float_exception_masks & float_flag_overflow) { - float_raise(round_status, float_flag_overflow); - return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp - 0x6000, zSig0, zSig1, status = round_status); - } - - return result; -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent -| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. This routine is just like -| `roundAndPackFloatx80' except that the input significand does not have to be -| normalized. -*----------------------------------------------------------------------------*/ - -floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) -{ - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - int shiftCount = countLeadingZeros64(zSig0); - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - zExp -= shiftCount; - return - roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status); -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -void normalizeFloat128Subnormal( - Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr) -{ - int shiftCount; - - if (aSig0 == 0) { - shiftCount = countLeadingZeros64(aSig1) - 15; - if (shiftCount < 0) { - *zSig0Ptr = aSig1 >>(-shiftCount); - *zSig1Ptr = aSig1 << (shiftCount & 63); - } - else { - *zSig0Ptr = aSig1 << shiftCount; - *zSig1Ptr = 0; - } - *zExpPtr = - shiftCount - 63; - } - else { - shiftCount = countLeadingZeros64(aSig0) - 15; - shortShift128Left(aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr); - *zExpPtr = 1 - shiftCount; - } -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 roundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status) -{ - int increment = ((Bit64s) zSig2 < 0); - if (0x7FFD <= (Bit32u) zExp) { - if ((0x7FFD < zExp) - || ((zExp == 0x7FFD) - && eq128(BX_CONST64(0x0001FFFFFFFFFFFF), - BX_CONST64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1) - && increment)) - { - float_raise(status, float_flag_overflow | float_flag_inexact); - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (zExp < 0) { - int isTiny = (zExp < -1) - || ! increment - || lt128(zSig0, zSig1, - BX_CONST64(0x0001FFFFFFFFFFFF), - BX_CONST64(0xFFFFFFFFFFFFFFFF)); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2); - zExp = 0; - if (isTiny && zSig2) float_raise(status, float_flag_underflow); - increment = ((Bit64s) zSig2 < 0); - } - } - if (zSig2) float_raise(status, float_flag_inexact); - if (increment) { - add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1); - zSig1 &= ~((zSig2 + zSig2 == 0) & 1); - } - else { - if ((zSig0 | zSig1) == 0) zExp = 0; - } - return packFloat128Four(zSign, zExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -float128 normalizeRoundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status) -{ - Bit64u zSig2; - - if (zSig0 == 0) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - int shiftCount = countLeadingZeros64(zSig0) - 15; - if (0 <= shiftCount) { - zSig2 = 0; - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, -shiftCount, &zSig0, &zSig1, &zSig2); - } - zExp -= shiftCount; - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -#endif diff --git a/src/cpu/softfloat/softfloat-round-pack.h b/src/cpu/softfloat/softfloat-round-pack.h deleted file mode 100644 index 1422aaea60..0000000000 --- a/src/cpu/softfloat/softfloat-round-pack.h +++ /dev/null @@ -1,309 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOAT_ROUND_PACK_H_ -#define _SOFTFLOAT_ROUND_PACK_H_ - -#include "softfloat.h" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s roundAndPackInt32(int zSign, Bit64u absZ, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit unsigned integer corresponding to the -| input. Ordinarily, the fixed-point input is simply rounded to an integer, -| with the inexact exception raised if the input cannot be represented exactly -| as an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status); - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal half-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper half-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the half-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 14 -| and 13, which is 4 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float16 roundAndPackFloat16(int zSign, Bit16s zExp, Bit16u zSig, struct float_status_t *status); - -#endif - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the single-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal single- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 30 -| and 29, which is 7 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 roundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloat64Subnormal(Bit64u aSig, Bit16s *zExpPtr, Bit64u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. Ordinarily, the abstract -| value is simply rounded and packed into the double-precision format, with -| the inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded -| to a subnormal number, and the underflow and inexact exceptions are raised -| if the abstract input cannot be represented exactly as a subnormal double- -| precision floating-point number. -| The input significand `zSig' has its binary point between bits 62 -| and 61, which is 10 bits to the left of the usual location. This shifted -| significand must be normalized or smaller. If `zSig' is not normalized, -| `zExp' must be 0; in that case, the result returned is a subnormal number, -| and it must not require rounding. In the usual case that `zSig' is -| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent. -| The handling of underflow and overflow follows the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 roundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal extended double-precision floating-point value -| represented by the denormalized significand `aSig'. The normalized exponent -| and significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| rounded and packed into the extended double-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal extended -| double-precision floating-point number. -| If `roundingPrecision' is 32 or 64, the result is rounded to the same -| number of bits as single or double precision, respectively. Otherwise, the -| result is rounded to the full precision of the extended double-precision -| format. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. The -| handling of underflow and overflow follows the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 roundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent -| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1', -| and returns the proper extended double-precision floating-point value -| corresponding to the abstract input. This routine is just like -| `roundAndPackFloatx80' except that the input significand does not have to be -| normalized. -*----------------------------------------------------------------------------*/ - -floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision, - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); - -#endif // FLOATX80 - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -void normalizeFloat128Subnormal( - Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 roundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -float128 normalizeRoundAndPackFloat128( - int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status); - -#endif // FLOAT128 - -#endif diff --git a/src/cpu/softfloat/softfloat-specialize.cc b/src/cpu/softfloat/softfloat-specialize.cc deleted file mode 100644 index bf0d111446..0000000000 --- a/src/cpu/softfloat/softfloat-specialize.cc +++ /dev/null @@ -1,187 +0,0 @@ -/*============================================================================ -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status) -{ - int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan(a); - aIsSignalingNaN = float32_is_signaling_nan(a); - bIsNaN = float32_is_nan(b); - bIsSignalingNaN = float32_is_signaling_nan(b); - a |= 0x00400000; - b |= 0x00400000; - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (get_float_nan_handling_mode(status) == float_larger_significand_nan) { - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if ((Bit32u) (a<<1) < (Bit32u) (b<<1)) return b; - if ((Bit32u) (b<<1) < (Bit32u) (a<<1)) return a; - return (a < b) ? a : b; - } - else { - return b; - } - } else { - return (aIsSignalingNaN | aIsNaN) ? a : b; - } -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status) -{ - int aIsNaN = float64_is_nan(a); - int aIsSignalingNaN = float64_is_signaling_nan(a); - int bIsNaN = float64_is_nan(b); - int bIsSignalingNaN = float64_is_signaling_nan(b); - a |= BX_CONST64(0x0008000000000000); - b |= BX_CONST64(0x0008000000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (get_float_nan_handling_mode(status) == float_larger_significand_nan) { - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if ((Bit64u) (a<<1) < (Bit64u) (b<<1)) return b; - if ((Bit64u) (b<<1) < (Bit64u) (a<<1)) return a; - return (a < b) ? a : b; - } - else { - return b; - } - } else { - return (aIsSignalingNaN | aIsNaN) ? a : b; - } -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status) -{ - int aIsNaN = floatx80_is_nan(a); - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsNaN = floatx80_is_nan(b); - int bIsSignalingNaN = floatx80_is_signaling_nan(b); - a.fraction |= BX_CONST64(0xC000000000000000); - b.fraction |= BX_CONST64(0xC000000000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | ! bIsNaN) return a; - returnLargerSignificand: - if (a.fraction < b.fraction) return b; - if (b.fraction < a.fraction) return a; - return (a.exp < b.exp) ? a : b; - } - else { - return b; - } -} - -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status) -{ - int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - aIsNaN = float128_is_nan(a); - aIsSignalingNaN = float128_is_signaling_nan(a); - bIsNaN = float128_is_nan(b); - bIsSignalingNaN = float128_is_signaling_nan(b); - a.hi |= BX_CONST64(0x0000800000000000); - b.hi |= BX_CONST64(0x0000800000000000); - if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid); - if (aIsSignalingNaN) { - if (bIsSignalingNaN) goto returnLargerSignificand; - return bIsNaN ? b : a; - } - else if (aIsNaN) { - if (bIsSignalingNaN | !bIsNaN) return a; - returnLargerSignificand: - if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b; - if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a; - return (a.hi < b.hi) ? a : b; - } - else { - return b; - } -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -const float128 float128_default_nan = - packFloat128(float128_default_nan_hi, float128_default_nan_lo); - -#endif /* FLOAT128 */ diff --git a/src/cpu/softfloat/softfloat-specialize.h b/src/cpu/softfloat/softfloat-specialize.h deleted file mode 100644 index 302ce53e43..0000000000 --- a/src/cpu/softfloat/softfloat-specialize.h +++ /dev/null @@ -1,789 +0,0 @@ -/*============================================================================ -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#ifndef _SOFTFLOAT_SPECIALIZE_H_ -#define _SOFTFLOAT_SPECIALIZE_H_ - -#include "softfloat.h" - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#define int16_indefinite ((Bit16s)0x8000) -#define int32_indefinite ((Bit32s)0x80000000) -#define int64_indefinite BX_CONST64(0x8000000000000000) - -#define uint16_indefinite (0xffff) -#define uint32_indefinite (0xffffffff) -#define uint64_indefinite BX_CONST64(0xffffffffffffffff) - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ - -typedef struct { - int sign; - Bit64u hi, lo; -} commonNaNT; - -#ifdef FLOAT16 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated half-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float16 float16_default_nan; - -#define float16_fraction extractFloat16Frac -#define float16_exp extractFloat16Exp -#define float16_sign extractFloat16Sign - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16u extractFloat16Frac(float16 a) -{ - return a & 0x3FF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat16Exp(float16 a) -{ - return (a>>10) & 0x1F; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the half-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat16Sign(float16 a) -{ - return a>>15; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 packFloat16(int zSign, int zExp, Bit16u zSig) -{ - return (((Bit16u) zSign)<<15) + (((Bit16u) zExp)<<10) + zSig; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_nan(float16 a) -{ - return (0xF800 < (Bit16u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_signaling_nan(float16 a) -{ - return (((a>>9) & 0x3F) == 0x3E) && (a & 0x1FF); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the half-precision floating-point value `a' is denormal; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float16_is_denormal(float16 a) -{ - return (extractFloat16Exp(a) == 0) && (extractFloat16Frac(a) != 0); -} - -/*---------------------------------------------------------------------------- -| Convert float16 denormals to zero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 float16_denormal_to_zero(float16 a) -{ - if (float16_is_denormal(a)) a &= 0x8000; - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the half-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float16ToCommonNaN(float16 a, struct float_status_t *status) -{ - commonNaNT z; - if (float16_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a>>15; - z.lo = 0; - z.hi = ((Bit64u) a)<<54; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the half- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float16 commonNaNToFloat16(commonNaNT a) -{ - return (((Bit16u) a.sign)<<15) | 0x7E00 | (Bit16u)(a.hi>>54); -} - -#endif - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -extern const float32 float32_negative_inf; -extern const float32 float32_positive_inf; -extern const float32 float32_negative_zero; -extern const float32 float32_positive_zero; -extern const float32 float32_negative_one; -extern const float32 float32_positive_one; -extern const float32 float32_max_float; -extern const float32 float32_min_float; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float32 float32_default_nan; - -#define float32_fraction extractFloat32Frac -#define float32_exp extractFloat32Exp -#define float32_sign extractFloat32Sign - -#define FLOAT32_EXP_BIAS 0x7F - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32u extractFloat32Frac(float32 a) -{ - return a & 0x007FFFFF; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat32Exp(float32 a) -{ - return (a>>23) & 0xFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat32Sign(float32 a) -{ - return a>>31; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| single-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 packFloat32(int zSign, Bit16s zExp, Bit32u zSig) -{ - return (((Bit32u) zSign)<<31) + (((Bit32u) zExp)<<23) + zSig; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_nan(float32 a) -{ - return (0xFF000000 < (Bit32u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_signaling_nan(float32 a) -{ - return (((a>>22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is denormal; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float32_is_denormal(float32 a) -{ - return (extractFloat32Exp(a) == 0) && (extractFloat32Frac(a) != 0); -} - -/*---------------------------------------------------------------------------- -| Convert float32 denormals to zero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 float32_denormal_to_zero(float32 a) -{ - if (float32_is_denormal(a)) a &= 0x80000000; - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float32ToCommonNaN(float32 a, struct float_status_t *status) -{ - commonNaNT z; - if (float32_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a>>31; - z.lo = 0; - z.hi = ((Bit64u) a)<<41; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 commonNaNToFloat32(commonNaNT a) -{ - return (((Bit32u) a.sign)<<31) | 0x7FC00000 | (Bit32u)(a.hi>>41); -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes single-precision floating-point NaN `a' and returns the appropriate -| NaN result. If `a' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float32 propagateFloat32NaNOne(float32 a, struct float_status_t *status) -{ - if (float32_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - return a | 0x00400000; -} - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -extern const float64 float64_negative_inf; -extern const float64 float64_positive_inf; -extern const float64 float64_negative_zero; -extern const float64 float64_positive_zero; -extern const float64 float64_negative_one; -extern const float64 float64_positive_one; -extern const float64 float64_max_float; -extern const float64 float64_min_float; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float64 float64_default_nan; - -#define float64_fraction extractFloat64Frac -#define float64_exp extractFloat64Exp -#define float64_sign extractFloat64Sign - -#define FLOAT64_EXP_BIAS 0x3FF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat64Frac(float64 a) -{ - return a & BX_CONST64(0x000FFFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit16s extractFloat64Exp(float64 a) -{ - return (Bit16s)(a>>52) & 0x7FF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat64Sign(float64 a) -{ - return (int)(a>>63); -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a -| double-precision floating-point value, returning the result. After being -| shifted into the proper positions, the three fields are simply added -| together to form the result. This means that any integer portion of `zSig' -| will be added into the exponent. Since a properly normalized significand -| will have an integer portion equal to 1, the `zExp' input should be 1 less -| than the desired result exponent whenever `zSig' is a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 packFloat64(int zSign, Bit16s zExp, Bit64u zSig) -{ - return (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<52) + zSig; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_nan(float64 a) -{ - return (BX_CONST64(0xFFE0000000000000) < (Bit64u) (a<<1)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_signaling_nan(float64 a) -{ - return (((a>>51) & 0xFFF) == 0xFFE) && (a & BX_CONST64(0x0007FFFFFFFFFFFF)); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is denormal; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float64_is_denormal(float64 a) -{ - return (extractFloat64Exp(a) == 0) && (extractFloat64Frac(a) != 0); -} - -/*---------------------------------------------------------------------------- -| Convert float64 denormals to zero. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 float64_denormal_to_zero(float64 a) -{ - if (float64_is_denormal(a)) a &= ((Bit64u)(1) << 63); - return a; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float64ToCommonNaN(float64 a, struct float_status_t *status) -{ - commonNaNT z; - if (float64_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = (int)(a>>63); - z.lo = 0; - z.hi = a<<12; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a) -{ - return (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FF8000000000000) | (a.hi>>12); -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes double-precision floating-point NaN `a' and returns the appropriate -| NaN result. If `a' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float64 propagateFloat64NaNOne(float64 a, struct float_status_t *status) -{ - if (float64_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - return a | BX_CONST64(0x0008000000000000); -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_exp 0xFFFF -#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000) - -#define floatx80_fraction extractFloatx80Frac -#define floatx80_exp extractFloatx80Exp -#define floatx80_sign extractFloatx80Sign - -#define FLOATX80_EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloatx80Frac(floatx80 a) -{ - return a.fraction; -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32s extractFloatx80Exp(floatx80 a) -{ - return a.exp & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloatx80Sign(floatx80 a) -{ - return a.exp>>15; -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an -| extended double-precision floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 packFloatx80(int zSign, Bit32s zExp, Bit64u zSig) -{ - floatx80 z; - z.fraction = zSig; - z.exp = (zSign << 15) + zExp; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_nan(floatx80 a) -{ - // return ((a.exp & 0x7FFF) == 0x7FFF) && (Bit64s) (a.fraction<<1); - return ((a.exp & 0x7FFF) == 0x7FFF) && (((Bit64s) (a.fraction<<1)) != 0); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_signaling_nan(floatx80 a) -{ - Bit64u aLow = a.fraction & ~BX_CONST64(0x4000000000000000); - return ((a.exp & 0x7FFF) == 0x7FFF) && - ((Bit64u) (aLow<<1)) && (a.fraction == aLow); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is an -| unsupported; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int floatx80_is_unsupported(floatx80 a) -{ - return ((a.exp & 0x7FFF) && !(a.fraction & BX_CONST64(0x8000000000000000))); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT floatx80ToCommonNaN(floatx80 a, struct float_status_t *status) -{ - commonNaNT z; - if (floatx80_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = a.exp >> 15; - z.lo = 0; - z.hi = a.fraction << 1; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 commonNaNToFloatx80(commonNaNT a) -{ - floatx80 z; - z.fraction = BX_CONST64(0xC000000000000000) | (a.hi>>1); - z.exp = (((Bit16u) a.sign)<<15) | 0x7FFF; - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Takes extended double-precision floating-point NaN `a' and returns the -| appropriate NaN result. If `a' is a signaling NaN, the invalid exception -| is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE floatx80 propagateFloatx80NaNOne(floatx80 a, struct float_status_t *status) -{ - if (floatx80_is_signaling_nan(a)) - float_raise(status, float_flag_invalid); - - a.fraction |= BX_CONST64(0xC000000000000000); - - return a; -} - -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_hi BX_CONST64(0xFFFF800000000000) -#define float128_default_nan_lo BX_CONST64(0x0000000000000000) - -#define float128_exp extractFloat128Exp - -/*---------------------------------------------------------------------------- -| Returns the least-significant 64 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat128Frac1(float128 a) -{ - return a.lo; -} - -/*---------------------------------------------------------------------------- -| Returns the most-significant 48 fraction bits of the quadruple-precision -| floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit64u extractFloat128Frac0(float128 a) -{ - return a.hi & BX_CONST64(0x0000FFFFFFFFFFFF); -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the quadruple-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE Bit32s extractFloat128Exp(float128 a) -{ - return ((Bit32s)(a.hi>>48)) & 0x7FFF; -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int extractFloat128Sign(float128 a) -{ - return (int)(a.hi >> 63); -} - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', the exponent `zExp', and the significand formed -| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision -| floating-point value, returning the result. After being shifted into the -| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply -| added together to form the most significant 32 bits of the result. This -| means that any integer portion of `zSig0' will be added into the exponent. -| Since a properly normalized significand will have an integer portion equal -| to 1, the `zExp' input should be 1 less than the desired result exponent -| whenever `zSig0' and `zSig1' concatenated form a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 packFloat128Four(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1) -{ - float128 z; - z.lo = zSig1; - z.hi = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0; - return z; -} - -/*---------------------------------------------------------------------------- -| Packs two 64-bit precision integers into into the quadruple-precision -| floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo) -{ - float128 z; - z.lo = zLo; - z.hi = zHi; - return z; -} - -#ifdef _MSC_VER -#define PACK_FLOAT_128(hi,lo) { lo, hi } -#else -#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo)) -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float128_is_nan(float128 a) -{ - return (BX_CONST64(0xFFFE000000000000) <= (Bit64u) (a.hi<<1)) - && (a.lo || (a.hi & BX_CONST64(0x0000FFFFFFFFFFFF))); -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float128_is_signaling_nan(float128 a) -{ - return (((a.hi>>47) & 0xFFFF) == 0xFFFE) - && (a.lo || (a.hi & BX_CONST64(0x00007FFFFFFFFFFF))); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE commonNaNT float128ToCommonNaN(float128 a, struct float_status_t *status) -{ - commonNaNT z; - if (float128_is_signaling_nan(a)) float_raise(status, float_flag_invalid); - z.sign = (int)(a.hi>>63); - shortShift128Left(a.hi, a.lo, 16, &z.hi, &z.lo); - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE float128 commonNaNToFloat128(commonNaNT a) -{ - float128 z; - shift128Right(a.hi, a.lo, 16, &z.hi, &z.lo); - z.hi |= (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FFF800000000000); - return z; -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. -*----------------------------------------------------------------------------*/ -extern const float128 float128_default_nan; - -#endif /* FLOAT128 */ - -#endif diff --git a/src/cpu/softfloat/softfloat.cc b/src/cpu/softfloat/softfloat.cc deleted file mode 100644 index 0802089b90..0000000000 --- a/src/cpu/softfloat/softfloat.cc +++ /dev/null @@ -1,4012 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -#define FLOAT128 - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" -#include "softfloat-round-pack.h" - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target -| if desired). -*----------------------------------------------------------------------------*/ -#define USE_estimateDiv128To64 -#define USE_estimateSqrt32 -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the single-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -const unsigned float_all_exceptions_mask = 0x3f; - -float32 int32_to_float32(Bit32s a, struct float_status_t *status) -{ - if (a == 0) return 0; - if (a == (Bit32s) 0x80000000) return packFloat32(1, 0x9E, 0); - int zSign = (a < 0); - return normalizeRoundAndPackFloat32(zSign, 0x9C, zSign ? -a : a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 int32_to_float64(Bit32s a) -{ - if (a == 0) return 0; - int zSign = (a < 0); - Bit32u absA = zSign ? -a : a; - int shiftCount = countLeadingZeros32(absA) + 21; - Bit64u zSig = absA; - return packFloat64(zSign, 0x432 - shiftCount, zSig<> 1, status); - return normalizeRoundAndPackFloat32(0, 0x9C, a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit unsigned integer `a' to the -| double-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 uint32_to_float64(Bit32u a) -{ - if (a == 0) return 0; - int shiftCount = countLeadingZeros32(a) + 21; - Bit64u zSig = a; - return packFloat64(0, 0x432 - shiftCount, zSig<> 1, status); - return normalizeRoundAndPackFloat64(0, 0x43C, a, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic - which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the -| conversion overflows the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float32_to_int32(float32 a, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - if ((aExp == 0xFF) && aSig) aSign = 0; - if (aExp) aSig |= 0x00800000; - else { - if (get_denormals_are_zeros(status)) aSig = 0; - } - int shiftCount = 0xAF - aExp; - Bit64u aSig64 = Bit64u(aSig) << 32; - if (0 < shiftCount) aSig64 = shift64RightJamming(aSig64, shiftCount); - return roundAndPackInt32(aSign, aSig64, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN or the conversion overflows, the integer indefinite -| value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float32_to_int32_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - Bit32s z; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0x9E; - if (0 <= shiftCount) { - if (a != 0xCF000000) { - float_raise(status, float_flag_invalid); - } - return (Bit32s)(int32_indefinite); - } - else if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - aSig = (aSig | 0x800000)<<8; - z = aSig>>(-shiftCount); - if ((Bit32u) (aSig<<(shiftCount & 31))) { - float_raise(status, float_flag_inexact); - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit unsigned integer format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN -| or conversion overflows, the largest positive integer is returned. -*----------------------------------------------------------------------------*/ - -Bit32u float32_to_uint32_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0x9E; - - if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - else if (0 < shiftCount || aSign) { - float_raise(status, float_flag_invalid); - return uint32_indefinite; - } - - aSig = (aSig | 0x800000)<<8; - Bit32u z = aSig >> (-shiftCount); - if (aSig << (shiftCount & 31)) { - float_raise(status, float_flag_inexact); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic - which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s float32_to_int64(float32 a, struct float_status_t *status) -{ - Bit64u aSig64, aSigExtra; - - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - - int shiftCount = 0xBE - aExp; - if (shiftCount < 0) { - float_raise(status, float_flag_invalid); - return (Bit64s)(int64_indefinite); - } - if (aExp) aSig |= 0x00800000; - else { - if (get_denormals_are_zeros(status)) aSig = 0; - } - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); - return roundAndPackInt64(aSign, aSig64, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN or the conversion overflows, the integer indefinite -| value is returned. -*----------------------------------------------------------------------------*/ - -Bit64s float32_to_int64_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - Bit64u aSig64; - Bit64s z; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0xBE; - if (0 <= shiftCount) { - if (a != 0xDF000000) { - float_raise(status, float_flag_invalid); - } - return (Bit64s)(int64_indefinite); - } - else if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>(-shiftCount); - if ((Bit64u) (aSig64<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN -| or the conversion overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float32_to_uint64_round_to_zero(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit32u aSig; - Bit64u aSig64; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - int shiftCount = aExp - 0xBE; - - if (aExp <= 0x7E) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - else if (0 < shiftCount || aSign) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - Bit64u z = aSig64>>(-shiftCount); - if ((Bit64u) (aSig64<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float32_to_uint64(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, shiftCount; - Bit32u aSig; - Bit64u aSig64, aSigExtra; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if ((aSign) && (aExp > 0x7E)) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - shiftCount = 0xBE - aExp; - if (aExp) aSig |= 0x00800000; - - if (shiftCount < 0) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); - return roundAndPackUint64(aSign, aSig64, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 32-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit32u float32_to_uint32(float32 a, struct float_status_t *status) -{ - Bit64u val_64 = float32_to_uint64(a, status); - - if (val_64 > 0xffffffff) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return uint32_indefinite; - } - - return (Bit32u) val_64; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64(float32 a, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return commonNaNToFloat64(float32ToCommonNaN(a, status)); - return packFloat64(aSign, 0x7FF, 0); - } - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat64(aSign, 0, 0); - - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - --aExp; - } - return packFloat64(aSign, aExp + 0x380, ((Bit64u) aSig)<<29); -} - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int(float32 a, Bit8u scale, struct float_status_t *status) -{ - Bit32u lastBitMask, roundBitsMask; - int roundingMode = get_float_rounding_mode(status); - Bit16s aExp = extractFloat32Exp(a); - scale &= 0xf; - - if ((aExp == 0xFF) && extractFloat32Frac(a)) { - return propagateFloat32NaNOne(a, status); - } - - aExp += scale; // scale the exponent - - if (0x96 <= aExp) { - return a; - } - - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - } - - if (aExp <= 0x7E) { - if ((Bit32u) (a<<1) == 0) return a; - float_raise(status, float_flag_inexact); - int aSign = extractFloat32Sign(a); - switch (roundingMode) { - case float_round_nearest_even: - if ((aExp == 0x7E) && extractFloat32Frac(a)) { - return packFloat32(aSign, 0x7F - scale, 0); - } - break; - case float_round_down: - return aSign ? packFloat32(1, 0x7F - scale, 0) : float32_positive_zero; - case float_round_up: - return aSign ? float32_negative_zero : packFloat32(0, 0x7F - scale, 0); - } - return packFloat32(aSign, 0, 0); - } - - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - float32 z = a; - if (roundingMode == float_round_nearest_even) { - z += lastBitMask>>1; - if ((z & roundBitsMask) == 0) z &= ~lastBitMask; - } - else if (roundingMode != float_round_to_zero) { - if (extractFloat32Sign(z) ^ (roundingMode == float_round_up)) { - z += roundBitsMask; - } - } - z &= ~roundBitsMask; - if (z != a) float_raise(status, float_flag_inexact); - return z; -} - -/*---------------------------------------------------------------------------- -| Extracts the fractional portion of single-precision floating-point value `a', -| and returns the result as a single-precision floating-point value. The -| fractional results are precise. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_frc(float32 a, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (aExp >= 0x96) { - return packFloat32(roundingMode == float_round_down, 0, 0); - } - - if (aExp < 0x7F) { - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat32(roundingMode == float_round_down, 0, 0); - - float_raise(status, float_flag_denormal); - if (! float_exception_masked(status, float_flag_underflow)) - float_raise(status, float_flag_underflow); - - if(get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat32(aSign, 0, 0); - } - } - return a; - } - - Bit32u lastBitMask = 1 << (0x96 - aExp); - Bit32u roundBitsMask = lastBitMask - 1; - - aSig &= roundBitsMask; - aSig <<= 7; - aExp--; - - if (aSig == 0) - return packFloat32(roundingMode == float_round_down, 0, 0); - - return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Extracts the exponent portion of single-precision floating-point value 'a', -| and returns the result as a single-precision floating-point value -| representing unbiased integer exponent. The operation is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_getexp(float32 a, struct float_status_t *status) -{ - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - return float32_positive_inf; - } - - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return float32_negative_inf; - - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - - return int32_to_float32(aExp - 0x7F, status); -} - -/*---------------------------------------------------------------------------- -| Extracts the mantissa of single-precision floating-point value 'a' and -| returns the result as a single-precision floating-point after applying -| the mantissa interval normalization and sign control. The operation is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv) -{ - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - } - return packFloat32(~sign_ctrl & aSign, 0x7F, 0); - } - - if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) { - return packFloat32(~sign_ctrl & aSign, 0x7F, 0); - } - - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); -// aExp += 0x7E; - aSig &= 0x7FFFFF; - } - - switch(interv) { - case 0x0: // interval [1,2) - aExp = 0x7F; - break; - case 0x1: // interval [1/2,2) - aExp -= 0x7F; - aExp = 0x7F - (aExp & 0x1); - break; - case 0x2: // interval [1/2,1) - aExp = 0x7E; - break; - case 0x3: // interval [3/4,3/2) - aExp = 0x7F - ((aSig >> 22) & 0x1); - break; - } - - return packFloat32(~sign_ctrl & aSign, aExp, aSig); -} - -/*---------------------------------------------------------------------------- -| Return the result of a floating point scale of the single-precision floating -| point value `a' by multiplying it by 2 power of the single-precision -| floating point value 'b' converted to integral value. If the result cannot -| be represented in single precision, then the proper overflow response (for -| positive scaling operand), or the proper underflow response (for negative -| scaling operand) is issued. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_scalef(float32 a, float32 b, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - Bit32u bSig = extractFloat32Frac(b); - Bit16s bExp = extractFloat32Exp(b); - int bSign = extractFloat32Sign(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - } - - if (aExp == 0xFF) { - if (aSig) { - int aIsSignalingNaN = (aSig & 0x00400000) == 0; - if (aIsSignalingNaN || bExp != 0xFF || bSig) - return propagateFloat32NaN(a, b, status); - - return bSign ? 0 : float32_positive_inf; - } - - if (bExp == 0xFF && bSign) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - return a; - } - - if (aExp == 0) { - if (aSig == 0) { - if (bExp == 0xFF && ! bSign) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - return a; - } - float_raise(status, float_flag_denormal); - } - - if ((bExp | bSig) == 0) return a; - - if (bExp == 0xFF) { - if (bSign) return packFloat32(aSign, 0, 0); - return packFloat32(aSign, 0xFF, 0); - } - - if (bExp >= 0x8E) { - // handle obvious overflow/underflow result - return roundAndPackFloat32(aSign, bSign ? -0x7F : 0xFF, aSig, status); - } - - int scale = 0; - - if (bExp <= 0x7E) { - if (bExp == 0) - float_raise(status, float_flag_denormal); - scale = -bSign; - } - else { - int shiftCount = bExp - 0x9E; - bSig = (bSig | 0x800000)<<8; - scale = bSig>>(-shiftCount); - - if (bSign) { - if ((Bit32u) (bSig<<(shiftCount & 31))) scale++; - scale = -scale; - } - - if (scale > 0x200) scale = 0x200; - if (scale < -0x200) scale = -0x200; - } - - if (aExp != 0) { - aSig |= 0x00800000; - } else { - aExp++; - } - - aExp += scale - 1; - aSig <<= 7; - return normalizeRoundAndPackFloat32(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - - if (0 < expDiff) { - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= 0x20000000; - - bSig = shift32RightJamming(bSig, expDiff); - zExp = aExp; - } - else if (expDiff < 0) { - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= 0x20000000; - - aSig = shift32RightJamming(aSig, -expDiff); - zExp = bExp; - } - else { - if (aExp == 0xFF) { - if (aSig | bSig) return propagateFloat32NaN(a, b, status); - return a; - } - if (aExp == 0) { - zSig = (aSig + bSig) >> 6; - if (aSig | bSig) { - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status) && (extractFloat32Frac(zSig) == zSig)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat32(zSign, 0, 0); - } - if (! float_exception_masked(status, float_flag_underflow)) { - if (extractFloat32Frac(zSig) == zSig) - float_raise(status, float_flag_underflow); - } - } - return packFloat32(zSign, 0, zSig); - } - zSig = 0x40000000 + aSig + bSig; - return roundAndPackFloat32(zSign, aExp, zSig, status); - } - aSig |= 0x20000000; - zSig = (aSig + bSig)<<1; - --zExp; - if ((Bit32s) zSig < 0) { - zSig = aSig + bSig; - ++zExp; - } - return roundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs(float32 a, float32 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if (0 < expDiff) goto aExpBigger; - if (expDiff < 0) goto bExpBigger; - if (aExp == 0xFF) { - if (aSig | bSig) return propagateFloat32NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (aExp == 0) { - if (aSig | bSig) float_raise(status, float_flag_denormal); - aExp = 1; - bExp = 1; - } - if (bSig < aSig) goto aBigger; - if (aSig < bSig) goto bBigger; - return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0); - bExpBigger: - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign ^ 1, 0xFF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= 0x40000000; - - aSig = shift32RightJamming(aSig, -expDiff); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= 0x40000000; - - bSig = shift32RightJamming(bSig, expDiff); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add(float32 a, float32 b, struct float_status_t *status) -{ - int aSign = extractFloat32Sign(a); - int bSign = extractFloat32Sign(b); - - if (aSign == bSign) { - return addFloat32Sigs(a, b, aSign, status); - } - else { - return subFloat32Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub(float32 a, float32 b, struct float_status_t *status) -{ - int aSign = extractFloat32Sign(a); - int bSign = extractFloat32Sign(b); - - if (aSign == bSign) { - return subFloat32Sigs(a, b, aSign, status); - } - else { - return addFloat32Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul(float32 a, float32 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig; - Bit64u zSig64; - Bit32u zSig; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0xFF) { - if (aSig || ((bExp == 0xFF) && bSig)) - return propagateFloat32NaN(a, b, status); - - if ((bExp | bSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloat32(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x7F; - aSig = (aSig | 0x00800000)<<7; - bSig = (bSig | 0x00800000)<<8; - zSig64 = shift64RightJamming(((Bit64u) aSig) * bSig, 32); - zSig = (Bit32u) zSig64; - if (0 <= (Bit32s) (zSig<<1)) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div(float32 a, float32 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit32u aSig, bSig, zSig; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - bSig = extractFloat32Frac(b); - bExp = extractFloat32Exp(b); - bSign = extractFloat32Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaN(a, b, status); - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0xFF, 0); - } - if (bExp == 0xFF) { - if (bSig) return propagateFloat32NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat32(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloat32(zSign, 0xFF, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) return packFloat32(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x7D; - aSig = (aSig | 0x00800000)<<7; - bSig = (bSig | 0x00800000)<<8; - if (bSig <= (aSig + aSig)) { - aSig >>= 1; - ++zExp; - } - zSig = (((Bit64u) aSig)<<32) / bSig; - if ((zSig & 0x3F) == 0) { - zSig |= ((Bit64u) bSig * zSig != ((Bit64u) aSig)<<32); - } - return roundAndPackFloat32(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt(float32 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, zExp; - Bit32u aSig, zSig; - Bit64u rem, term; - - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return propagateFloat32NaNOne(a, status); - if (! aSign) return a; - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if (aSign) { - if ((aExp | aSig) == 0) return packFloat32(aSign, 0, 0); - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - if (aExp == 0) { - if (aSig == 0) return 0; - float_raise(status, float_flag_denormal); - normalizeFloat32Subnormal(aSig, &aExp, &aSig); - } - zExp = ((aExp - 0x7F)>>1) + 0x7E; - aSig = (aSig | 0x00800000)<<8; - zSig = estimateSqrt32(aExp, aSig) + 2; - if ((zSig & 0x7F) <= 5) { - if (zSig < 2) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ((Bit64u) zSig) * zSig; - rem = (((Bit64u) aSig)<<32) - term; - while ((Bit64s) rem < 0) { - --zSig; - rem += (((Bit64u) zSig)<<1) | 1; - } - zSig |= (rem != 0); - } - zSig = shift32RightJamming(zSig, 1); - roundAndPack: - return roundAndPackFloat32(0, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Determine single-precision floating-point number class. -*----------------------------------------------------------------------------*/ - -float_class_t float32_class(float32 a) -{ - Bit16s aExp = extractFloat32Exp(a); - Bit32u aSig = extractFloat32Frac(a); - int aSign = extractFloat32Sign(a); - - if(aExp == 0xFF) { - if (aSig == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & 0x00400000) ? float_QNaN : float_SNaN; - } - - if(aExp == 0) { - if (aSig == 0) return float_zero; - return float_denormal; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -int float32_compare(float32 a, float32 b, int quiet, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - float_class_t aClass = float32_class(a); - float_class_t bClass = float32_class(b); - - if (aClass == float_SNaN || bClass == float_SNaN) { - float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_QNaN || bClass == float_QNaN) { - if (! quiet) float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) { - float_raise(status, float_flag_denormal); - } - - if ((a == b) || ((Bit32u) ((a | b)<<1) == 0)) return float_relation_equal; - - int aSign = extractFloat32Sign(a); - int bSign = extractFloat32Sign(b); - if (aSign != bSign) - return (aSign) ? float_relation_less : float_relation_greater; - - if (aSign ^ (a < b)) return float_relation_less; - return float_relation_greater; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers and return the -| smaller of them. -*----------------------------------------------------------------------------*/ - -float32 float32_min(float32 a, float32 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - return (float32_compare_two(a, b, status) == float_relation_less) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers and return the -| larger of them. -*----------------------------------------------------------------------------*/ - -float32 float32_max(float32 a, float32 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - return (float32_compare_two(a, b, status) == float_relation_greater) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two single precision floating point numbers and return the -| smaller/larger of them. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float32_denormal_to_zero(a); - b = float32_denormal_to_zero(b); - } - - if (float32_is_nan(a) || float32_is_nan(b)) { - if (float32_is_signaling_nan(a)) { - return propagateFloat32NaNOne(a, status); - } - if (float32_is_signaling_nan(b) ) { - return propagateFloat32NaNOne(b, status); - } - if (! float32_is_nan(b)) { - if (float32_is_denormal(b)) - float_raise(status, float_flag_denormal); - return b; - } - if (! float32_is_nan(a)) { - if (float32_is_denormal(a)) - float_raise(status, float_flag_denormal); - return a; - } - return propagateFloat32NaN(a, b, status); - } - - float32 tmp_a = a, tmp_b = b; - if (is_abs) { - tmp_a &= ~0x80000000; // clear the sign bit - tmp_b &= ~0x80000000; - } - - int aSign = extractFloat32Sign(tmp_a); - int bSign = extractFloat32Sign(tmp_b); - - if (float32_is_denormal(a) || float32_is_denormal(b)) - float_raise(status, float_flag_denormal); - - if (aSign != bSign) { - if (! is_max) { - return aSign ? a : b; - } else { - return aSign ? b : a; - } - } else { - if (! is_max) { - return (aSign ^ (tmp_a < tmp_b)) ? a : b; - } else { - return (aSign ^ (tmp_a < tmp_b)) ? b : a; - } - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic - which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float64_to_int32(float64 a, struct float_status_t *status) -{ - Bit64u aSig = extractFloat64Frac(a); - Bit16s aExp = extractFloat64Exp(a); - int aSign = extractFloat64Sign(a); - if ((aExp == 0x7FF) && aSig) aSign = 0; - if (aExp) aSig |= BX_CONST64(0x0010000000000000); - else { - if (get_denormals_are_zeros(status)) aSig = 0; - } - int shiftCount = 0x42C - aExp; - if (0 < shiftCount) aSig = shift64RightJamming(aSig, shiftCount); - return roundAndPackInt32(aSign, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN or the conversion overflows, the integer indefinite -| value is returned. -*----------------------------------------------------------------------------*/ - -Bit32s float64_to_int32_round_to_zero(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit64u aSig, savedASig; - Bit32s z; - int shiftCount; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (0x41E < aExp) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - else if (aExp < 0x3FF) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp || aSig) float_raise(status, float_flag_inexact); - return 0; - } - aSig |= BX_CONST64(0x0010000000000000); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = (Bit32s) aSig; - if (aSign) z = -z; - if ((z < 0) ^ aSign) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if ((aSig<>= shiftCount; - if ((aSig<>(-shiftCount); - if ((Bit64u) (aSig<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic, -| except that the conversion is always rounded toward zero. If `a' is a NaN -| or the conversion overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float64_to_uint64_round_to_zero(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit64u aSig, z; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (aExp < 0x3FE) { - if (get_denormals_are_zeros(status) && aExp == 0) aSig = 0; - if (aExp | aSig) float_raise(status, float_flag_inexact); - return 0; - } - - if (0x43E <= aExp || aSign) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - if (aExp) aSig |= BX_CONST64(0x0010000000000000); - int shiftCount = aExp - 0x433; - - if (0 <= shiftCount) { - z = aSig<>(-shiftCount); - if ((Bit64u) (aSig<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit32u float64_to_uint32(float64 a, struct float_status_t *status) -{ - Bit64u val_64 = float64_to_uint64(a, status); - - if (val_64 > 0xffffffff) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return uint32_indefinite; - } - - return (Bit32u) val_64; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 64-bit unsigned integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN or the conversion -| overflows, the largest unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -Bit64u float64_to_uint64(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, shiftCount; - Bit64u aSig, aSigExtra; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if (aSign && (aExp > 0x3FE)) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - - if (aExp) { - aSig |= BX_CONST64(0x0010000000000000); - } - shiftCount = 0x433 - aExp; - if (shiftCount <= 0) { - if (0x43E < aExp) { - float_raise(status, float_flag_invalid); - return uint64_indefinite; - } - aSigExtra = 0; - aSig <<= -shiftCount; - } else { - shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); - } - - return roundAndPackUint64(aSign, aSig, aSigExtra, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp; - Bit64u aSig; - Bit32u zSig; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - if (aExp == 0x7FF) { - if (aSig) return commonNaNToFloat32(float64ToCommonNaN(a, status)); - return packFloat32(aSign, 0xFF, 0); - } - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat32(aSign, 0, 0); - float_raise(status, float_flag_denormal); - } - aSig = shift64RightJamming(aSig, 22); - zSig = (Bit32u) aSig; - if (aExp || zSig) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32(aSign, aExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int(float64 a, Bit8u scale, struct float_status_t *status) -{ - Bit64u lastBitMask, roundBitsMask; - int roundingMode = get_float_rounding_mode(status); - Bit16s aExp = extractFloat64Exp(a); - scale &= 0xf; - - if ((aExp == 0x7FF) && extractFloat64Frac(a)) { - return propagateFloat64NaNOne(a, status); - } - - aExp += scale; // scale the exponent - - if (0x433 <= aExp) { - return a; - } - - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - } - - if (aExp < 0x3FF) { - if ((Bit64u) (a<<1) == 0) return a; - float_raise(status, float_flag_inexact); - int aSign = extractFloat64Sign(a); - switch (roundingMode) { - case float_round_nearest_even: - if ((aExp == 0x3FE) && extractFloat64Frac(a)) { - return packFloat64(aSign, 0x3FF - scale, 0); - } - break; - case float_round_down: - return aSign ? packFloat64(1, 0x3FF - scale, 0) : float64_positive_zero; - case float_round_up: - return aSign ? float64_negative_zero : packFloat64(0, 0x3FF - scale, 0); - } - return packFloat64(aSign, 0, 0); - } - - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - float64 z = a; - if (roundingMode == float_round_nearest_even) { - z += lastBitMask>>1; - if ((z & roundBitsMask) == 0) z &= ~lastBitMask; - } - else if (roundingMode != float_round_to_zero) { - if (extractFloat64Sign(z) ^ (roundingMode == float_round_up)) { - z += roundBitsMask; - } - } - z &= ~roundBitsMask; - if (z != a) float_raise(status, float_flag_inexact); - return z; -} - -/*---------------------------------------------------------------------------- -| Extracts the fractional portion of double-precision floating-point value `a', -| and returns the result as a double-precision floating-point value. The -| fractional results are precise. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_frc(float64 a, struct float_status_t *status) -{ - int roundingMode = get_float_rounding_mode(status); - - Bit64u aSig = extractFloat64Frac(a); - Bit16s aExp = extractFloat64Exp(a); - int aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - if (aExp >= 0x433) { - return packFloat64(roundingMode == float_round_down, 0, 0); - } - - if (aExp < 0x3FF) { - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return packFloat64(roundingMode == float_round_down, 0, 0); - - float_raise(status, float_flag_denormal); - if (! float_exception_masked(status, float_flag_underflow)) - float_raise(status, float_flag_underflow); - - if(get_flush_underflow_to_zero(status)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat64(aSign, 0, 0); - } - } - return a; - } - - Bit64u lastBitMask = BX_CONST64(1) << (0x433 - aExp); - Bit64u roundBitsMask = lastBitMask - 1; - - aSig &= roundBitsMask; - aSig <<= 10; - aExp--; - - if (aSig == 0) - return packFloat64(roundingMode == float_round_down, 0, 0); - - return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Extracts the exponent portion of double-precision floating-point value 'a', -| and returns the result as a double-precision floating-point value -| representing unbiased integer exponent. The operation is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_getexp(float64 a, struct float_status_t *status) -{ - Bit16s aExp = extractFloat64Exp(a); - Bit64u aSig = extractFloat64Frac(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - return float64_positive_inf; - } - - if (aExp == 0) { - if (aSig == 0 || get_denormals_are_zeros(status)) - return float64_negative_inf; - - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - - return int32_to_float64(aExp - 0x3FF); -} - -/*---------------------------------------------------------------------------- -| Extracts the mantissa of double-precision floating-point value 'a' and -| returns the result as a double-precision floating-point after applying -| the mantissa interval normalization and sign control. The operation is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv) -{ - Bit16s aExp = extractFloat64Exp(a); - Bit64u aSig = extractFloat64Frac(a); - int aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - } - return packFloat64(~sign_ctrl & aSign, 0x3FF, 0); - } - - if (aExp == 0 && (aSig == 0 || get_denormals_are_zeros(status))) { - return packFloat64(~sign_ctrl & aSign, 0x3FF, 0); - } - - if (aSign) { - if (sign_ctrl & 0x2) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - } - - if (aExp == 0) { - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); -// aExp += 0x3FE; - aSig &= BX_CONST64(0xFFFFFFFFFFFFFFFF); - } - - switch(interv) { - case 0x0: // interval [1,2) - aExp = 0x3FF; - break; - case 0x1: // interval [1/2,2) - aExp -= 0x3FF; - aExp = 0x3FF - (aExp & 0x1); - break; - case 0x2: // interval [1/2,1) - aExp = 0x3FE; - break; - case 0x3: // interval [3/4,3/2) - aExp = 0x3FF - ((aSig >> 51) & 0x1); - break; - } - - return packFloat64(~sign_ctrl & aSign, aExp, aSig); -} - -/*---------------------------------------------------------------------------- -| Return the result of a floating point scale of the double-precision floating -| point value `a' by multiplying it by 2 power of the double-precision -| floating point value 'b' converted to integral value. If the result cannot -| be represented in double precision, then the proper overflow response (for -| positive scaling operand), or the proper underflow response (for negative -| scaling operand) is issued. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_scalef(float64 a, float64 b, struct float_status_t *status) -{ - Bit64u aSig = extractFloat64Frac(a); - Bit16s aExp = extractFloat64Exp(a); - int aSign = extractFloat64Sign(a); - Bit64u bSig = extractFloat64Frac(b); - Bit16s bExp = extractFloat64Exp(b); - int bSign = extractFloat64Sign(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - } - - if (aExp == 0x7FF) { - if (aSig) { - int aIsSignalingNaN = (aSig & BX_CONST64(0x0008000000000000)) == 0; - if (aIsSignalingNaN || bExp != 0x7FF || bSig) - return propagateFloat64NaN(a, b, status); - - return bSign ? 0 : float64_positive_inf; - } - - if (bExp == 0x7FF && bSign) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - return a; - } - - if (aExp == 0) { - if (aSig == 0) { - if (bExp == 0x7FF && ! bSign) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - return a; - } - float_raise(status, float_flag_denormal); - } - - if ((bExp | bSig) == 0) return a; - - if (bExp == 0x7FF) { - if (bSign) return packFloat64(aSign, 0, 0); - return packFloat64(aSign, 0x7FF, 0); - } - - if (0x40F <= bExp) { - // handle obvious overflow/underflow result - return roundAndPackFloat64(aSign, bSign ? -0x3FF : 0x7FF, aSig, status); - } - - int scale = 0; - - if (bExp < 0x3FF) { - if (bExp == 0) - float_raise(status, float_flag_denormal); - scale = -bSign; - } - else { - bSig |= BX_CONST64(0x0010000000000000); - int shiftCount = 0x433 - bExp; - Bit64u savedBSig = bSig; - bSig >>= shiftCount; - scale = (Bit32s) bSig; - if (bSign) { - if ((bSig< 0x1000) scale = 0x1000; - if (scale < -0x1000) scale = -0x1000; - } - - if (aExp != 0) { - aSig |= BX_CONST64(0x0010000000000000); - } else { - aExp++; - } - - aExp += scale - 1; - aSig <<= 10; - return normalizeRoundAndPackFloat64(aSign, aExp, aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if (0 < expDiff) { - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= BX_CONST64(0x2000000000000000); - - bSig = shift64RightJamming(bSig, expDiff); - zExp = aExp; - } - else if (expDiff < 0) { - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= BX_CONST64(0x2000000000000000); - - aSig = shift64RightJamming(aSig, -expDiff); - zExp = bExp; - } - else { - if (aExp == 0x7FF) { - if (aSig | bSig) return propagateFloat64NaN(a, b, status); - return a; - } - if (aExp == 0) { - zSig = (aSig + bSig) >> 9; - if (aSig | bSig) { - float_raise(status, float_flag_denormal); - if (get_flush_underflow_to_zero(status) && (extractFloat64Frac(zSig) == zSig)) { - float_raise(status, float_flag_underflow | float_flag_inexact); - return packFloat64(zSign, 0, 0); - } - if (! float_exception_masked(status, float_flag_underflow)) { - if (extractFloat64Frac(zSig) == zSig) - float_raise(status, float_flag_underflow); - } - } - return packFloat64(zSign, 0, zSig); - } - zSig = BX_CONST64(0x4000000000000000) + aSig + bSig; - return roundAndPackFloat64(zSign, aExp, zSig, status); - } - aSig |= BX_CONST64(0x2000000000000000); - zSig = (aSig + bSig)<<1; - --zExp; - if ((Bit64s) zSig < 0) { - zSig = aSig + bSig; - ++zExp; - } - return roundAndPackFloat64(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs(float64 a, float64 b, int zSign, struct float_status_t *status) -{ - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig; - Bit16s expDiff; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if (0 < expDiff) goto aExpBigger; - if (expDiff < 0) goto bExpBigger; - if (aExp == 0x7FF) { - if (aSig | bSig) return propagateFloat64NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (aExp == 0) { - if (aSig | bSig) float_raise(status, float_flag_denormal); - aExp = 1; - bExp = 1; - } - if (bSig < aSig) goto aBigger; - if (aSig < bSig) goto bBigger; - return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0); - bExpBigger: - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign ^ 1, 0x7FF, 0); - } - if ((bExp == 0) && bSig) - float_raise(status, float_flag_denormal); - - if (aExp == 0) { - if (aSig) float_raise(status, float_flag_denormal); - ++expDiff; - } - else aSig |= BX_CONST64(0x4000000000000000); - - aSig = shift64RightJamming(aSig, -expDiff); - bSig |= BX_CONST64(0x4000000000000000); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if ((aExp == 0) && aSig) - float_raise(status, float_flag_denormal); - - if (bExp == 0) { - if (bSig) float_raise(status, float_flag_denormal); - --expDiff; - } - else bSig |= BX_CONST64(0x4000000000000000); - - bSig = shift64RightJamming(bSig, expDiff); - aSig |= BX_CONST64(0x4000000000000000); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add(float64 a, float64 b, struct float_status_t *status) -{ - int aSign = extractFloat64Sign(a); - int bSign = extractFloat64Sign(b); - - if (aSign == bSign) { - return addFloat64Sigs(a, b, aSign, status); - } - else { - return subFloat64Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub(float64 a, float64 b, struct float_status_t *status) -{ - int aSign = extractFloat64Sign(a); - int bSign = extractFloat64Sign(b); - - if (aSign == bSign) { - return subFloat64Sigs(a, b, aSign, status); - } - else { - return addFloat64Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul(float64 a, float64 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0x7FF) { - if (aSig || ((bExp == 0x7FF) && bSig)) { - return propagateFloat64NaN(a, b, status); - } - if ((bExp | bSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloat64(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x3FF; - aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; - bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; - mul64To128(aSig, bSig, &zSig0, &zSig1); - zSig0 |= (zSig1 != 0); - if (0 <= (Bit64s) (zSig0<<1)) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64(zSign, zExp, zSig0, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div(float64 a, float64 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit16s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig; - Bit64u rem0, rem1; - Bit64u term0, term1; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - bSig = extractFloat64Frac(b); - bExp = extractFloat64Exp(b); - bSign = extractFloat64Sign(b); - zSign = aSign ^ bSign; - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - if (bExp == 0) bSig = 0; - } - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaN(a, b, status); - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0x7FF, 0); - } - if (bExp == 0x7FF) { - if (bSig) return propagateFloat64NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloat64(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloat64(zSign, 0x7FF, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) return packFloat64(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x3FD; - aSig = (aSig | BX_CONST64(0x0010000000000000))<<10; - bSig = (bSig | BX_CONST64(0x0010000000000000))<<11; - if (bSig <= (aSig + aSig)) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64(aSig, 0, bSig); - if ((zSig & 0x1FF) <= 2) { - mul64To128(bSig, zSig, &term0, &term1); - sub128(aSig, 0, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig; - add128(rem0, rem1, 0, bSig, &rem0, &rem1); - } - zSig |= (rem1 != 0); - } - return roundAndPackFloat64(zSign, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt(float64 a, struct float_status_t *status) -{ - int aSign; - Bit16s aExp, zExp; - Bit64u aSig, zSig, doubleZSig; - Bit64u rem0, rem1, term0, term1; - - aSig = extractFloat64Frac(a); - aExp = extractFloat64Exp(a); - aSign = extractFloat64Sign(a); - - if (aExp == 0x7FF) { - if (aSig) return propagateFloat64NaNOne(a, status); - if (! aSign) return a; - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - if (get_denormals_are_zeros(status)) { - if (aExp == 0) aSig = 0; - } - - if (aSign) { - if ((aExp | aSig) == 0) return packFloat64(aSign, 0, 0); - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - if (aExp == 0) { - if (aSig == 0) return 0; - float_raise(status, float_flag_denormal); - normalizeFloat64Subnormal(aSig, &aExp, &aSig); - } - zExp = ((aExp - 0x3FF)>>1) + 0x3FE; - aSig |= BX_CONST64(0x0010000000000000); - zSig = estimateSqrt32(aExp, (Bit32u)(aSig>>21)); - aSig <<= 9 - (aExp & 1); - zSig = estimateDiv128To64(aSig, 0, zSig<<32) + (zSig<<30); - if ((zSig & 0x1FF) <= 5) { - doubleZSig = zSig<<1; - mul64To128(zSig, zSig, &term0, &term1); - sub128(aSig, 0, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig; - doubleZSig -= 2; - add128(rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1); - } - zSig |= ((rem0 | rem1) != 0); - } - return roundAndPackFloat64(0, zExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Determine double-precision floating-point number class -*----------------------------------------------------------------------------*/ - -float_class_t float64_class(float64 a) -{ - Bit16s aExp = extractFloat64Exp(a); - Bit64u aSig = extractFloat64Frac(a); - int aSign = extractFloat64Sign(a); - - if(aExp == 0x7FF) { - if (aSig == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & BX_CONST64(0x0008000000000000)) ? float_QNaN : float_SNaN; - } - - if(aExp == 0) { - if (aSig == 0) - return float_zero; - return float_denormal; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -int float64_compare(float64 a, float64 b, int quiet, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - float_class_t aClass = float64_class(a); - float_class_t bClass = float64_class(b); - - if (aClass == float_SNaN || bClass == float_SNaN) { - float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_QNaN || bClass == float_QNaN) { - if (! quiet) float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) { - float_raise(status, float_flag_denormal); - } - - if ((a == b) || ((Bit64u) ((a | b)<<1) == 0)) return float_relation_equal; - - int aSign = extractFloat64Sign(a); - int bSign = extractFloat64Sign(b); - if (aSign != bSign) - return (aSign) ? float_relation_less : float_relation_greater; - - if (aSign ^ (a < b)) return float_relation_less; - return float_relation_greater; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers and return the -| smaller of them. -*----------------------------------------------------------------------------*/ - -float64 float64_min(float64 a, float64 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - return (float64_compare_two(a, b, status) == float_relation_less) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers and return the -| larger of them. -*----------------------------------------------------------------------------*/ - -float64 float64_max(float64 a, float64 b, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - return (float64_compare_two(a, b, status) == float_relation_greater) ? a : b; -} - -/*---------------------------------------------------------------------------- -| Compare between two double precision floating point numbers and return the -| smaller/larger of them. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status) -{ - if (get_denormals_are_zeros(status)) { - a = float64_denormal_to_zero(a); - b = float64_denormal_to_zero(b); - } - - if (float64_is_nan(a) || float64_is_nan(b)) { - if (float64_is_signaling_nan(a)) { - return propagateFloat64NaNOne(a, status); - } - if (float64_is_signaling_nan(b)) { - return propagateFloat64NaNOne(b, status); - } - if (! float64_is_nan(b)) { - if (float64_is_denormal(b)) - float_raise(status, float_flag_denormal); - return b; - } - if (! float64_is_nan(a)) { - if (float64_is_denormal(a)) - float_raise(status, float_flag_denormal); - return a; - } - return propagateFloat64NaN(a, b, status); - } - - float64 tmp_a = a, tmp_b = b; - if (is_abs) { - tmp_a &= ~BX_CONST64(0x8000000000000000); // clear the sign bit - tmp_b &= ~BX_CONST64(0x8000000000000000); - } - - int aSign = extractFloat64Sign(tmp_a); - int bSign = extractFloat64Sign(tmp_b); - - if (float64_is_denormal(a) || float64_is_denormal(b)) - float_raise(status, float_flag_denormal); - - if (aSign != bSign) { - if (! is_max) { - return aSign ? a : b; - } else { - return aSign ? b : a; - } - } else { - if (! is_max) { - return (aSign ^ (tmp_a < tmp_b)) ? a : b; - } else { - return (aSign ^ (tmp_a < tmp_b)) ? b : a; - } - } -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 32-bit two's complement integer `a' -| to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 int32_to_floatx80(Bit32s a) -{ - if (a == 0) return packFloatx80(0, 0, 0); - int zSign = (a < 0); - Bit32u absA = zSign ? -a : a; - int shiftCount = countLeadingZeros32(absA) + 32; - Bit64u zSig = absA; - return packFloatx80(zSign, 0x403E - shiftCount, zSig< 0x401E) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if (aExp < 0x3FFF) { - if (aExp || aSig) float_raise(status, float_flag_inexact); - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = (Bit32s) aSig; - if (aSign) z = -z; - if ((z < 0) ^ aSign) { - float_raise(status, float_flag_invalid); - return (Bit32s)(int32_indefinite); - } - if ((aSig<>(-shiftCount); - if ((Bit64u) (aSig<<(shiftCount & 63))) { - float_raise(status, float_flag_inexact); - } - if (aSign) z = -z; - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32(floatx80 a, struct float_status_t *status) -{ - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return float32_default_nan; - } - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return commonNaNToFloat32(floatx80ToCommonNaN(a, status)); - - return packFloat32(aSign, 0xFF, 0); - } - aSig = shift64RightJamming(aSig, 33); - if (aExp || aSig) aExp -= 0x3F81; - return roundAndPackFloat32(aSign, aExp, (Bit32u) aSig, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64(floatx80 a, struct float_status_t *status) -{ - Bit32s aExp; - Bit64u aSig, zSig; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return float64_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) { - return commonNaNToFloat64(floatx80ToCommonNaN(a, status)); - } - return packFloat64(aSign, 0x7FF, 0); - } - zSig = shift64RightJamming(aSig, 1); - if (aExp || aSig) aExp -= 0x3C01; - return roundAndPackFloat64(aSign, aExp, zSig, status); -} - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended double-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int(floatx80 a, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign; - Bit64u lastBitMask, roundBitsMask; - int roundingMode = get_float_rounding_mode(status); - floatx80 z; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - Bit32s aExp = extractFloatx80Exp(a); - Bit64u aSig = extractFloatx80Frac(a); - if (0x403E <= aExp) { - if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) { - return propagateFloatx80NaNOne(a, status); - } - return a; - } - if (aExp < 0x3FFF) { - if (aExp == 0) { - if ((aSig<<1) == 0) return a; - float_raise(status, float_flag_denormal); - } - float_raise(status, float_flag_inexact); - aSign = extractFloatx80Sign(a); - switch (roundingMode) { - case float_round_nearest_even: - if ((aExp == 0x3FFE) && (Bit64u) (aSig<<1)) { - set_float_rounding_up(status); - return packFloatx80(aSign, 0x3FFF, BX_CONST64(0x8000000000000000)); - } - break; - case float_round_down: - if (aSign) { - set_float_rounding_up(status); - return packFloatx80(1, 0x3FFF, BX_CONST64(0x8000000000000000)); - } - else { - return packFloatx80(0, 0, 0); - } - case float_round_up: - if (aSign) { - return packFloatx80(1, 0, 0); - } - else { - set_float_rounding_up(status); - return packFloatx80(0, 0x3FFF, BX_CONST64(0x8000000000000000)); - } - } - return packFloatx80(aSign, 0, 0); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - if (roundingMode == float_round_nearest_even) { - z.fraction += lastBitMask>>1; - if ((z.fraction & roundBitsMask) == 0) z.fraction &= ~lastBitMask; - } - else if (roundingMode != float_round_to_zero) { - if (extractFloatx80Sign(z) ^ (roundingMode == float_round_up)) - z.fraction += roundBitsMask; - } - z.fraction &= ~roundBitsMask; - if (z.fraction == 0) { - z.exp++; - z.fraction = BX_CONST64(0x8000000000000000); - } - if (z.fraction != a.fraction) { - float_raise(status, float_flag_inexact); - if (z.fraction > a.fraction || z.exp > a.exp) - set_float_rounding_up(status); - } - return z; -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - return propagateFloatx80NaN(a, b, status); - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp == 0) && bSig) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, bExp, bSig, 0, status); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, aExp, aSig, 0, status); - - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - Bit32s expDiff = aExp - bExp; - zExp = aExp; - if (0 < expDiff) { - shift64ExtraRightJamming(bSig, 0, expDiff, &bSig, &zSig1); - } - else if (expDiff < 0) { - shift64ExtraRightJamming(aSig, 0, -expDiff, &aSig, &zSig1); - zExp = bExp; - } - else { - zSig0 = aSig + bSig; - zSig1 = 0; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ((Bit64s) zSig0 < 0) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming(zSig0, zSig1, 1, &zSig0, &zSig1); - zSig0 |= BX_CONST64(0x8000000000000000); - zExp++; - roundAndPack: - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs(floatx80 a, floatx80 b, int zSign, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status); - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign ^ 1, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if (bExp == 0) { - if (bSig) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign ^ 1, bExp, bSig, 0, status); - } - return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0); - } - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign ^ 1, bExp, bSig, 0, status); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) - return roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, aExp, aSig, 0, status); - - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - Bit32s expDiff = aExp - bExp; - if (0 < expDiff) { - shift128RightJamming(bSig, 0, expDiff, &bSig, &zSig1); - goto aBigger; - } - if (expDiff < 0) { - shift128RightJamming(aSig, 0, -expDiff, &aSig, &zSig1); - goto bBigger; - } - zSig1 = 0; - if (bSig < aSig) goto aBigger; - if (aSig < bSig) goto bBigger; - return packFloatx80(get_float_rounding_mode(status) == float_round_down, 0, 0); - bBigger: - sub128(bSig, 0, aSig, zSig1, &zSig0, &zSig1); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aBigger: - sub128(aSig, 0, bSig, zSig1, &zSig0, &zSig1); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add(floatx80 a, floatx80 b, struct float_status_t *status) -{ - int aSign = extractFloatx80Sign(a); - int bSign = extractFloatx80Sign(b); - - if (aSign == bSign) - return addFloatx80Sigs(a, b, aSign, status); - else - return subFloatx80Sigs(a, b, aSign, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub(floatx80 a, floatx80 b, struct float_status_t *status) -{ - int aSign = extractFloatx80Sign(a); - int bSign = extractFloatx80Sign(b); - - if (aSign == bSign) - return subFloatx80Sigs(a, b, aSign, status); - else - return addFloatx80Sigs(a, b, aSign, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul(floatx80 a, floatx80 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - invalid: - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { - return propagateFloatx80NaN(a, b, status); - } - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128(aSig, bSig, &zSig0, &zSig1); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div(floatx80 a, floatx80 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig, zSig0, zSig1; - Bit64u rem0, rem1, rem2, term0, term1, term2; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); - - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) return propagateFloatx80NaN(a, b, status); - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - if (aExp == 0) { - if (aSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if (bSig <= aSig) { - shift128Right(aSig, 0, 1, &aSig, &rem1); - ++zExp; - } - zSig0 = estimateDiv128To64(aSig, rem1, bSig); - mul64To128(bSig, zSig0, &term0, &term1); - sub128(aSig, rem1, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig0; - add128(rem0, rem1, 0, bSig, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, bSig); - if ((Bit64u) (zSig1<<1) <= 8) { - mul64To128(bSig, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - while ((Bit64s) rem1 < 0) { - --zSig1; - add128(rem1, rem2, 0, bSig, &rem1, &rem2); - } - zSig1 |= ((rem1 | rem2) != 0); - } - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt(floatx80 a, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - int aSign; - Bit32s aExp, zExp; - Bit64u aSig0, aSig1, zSig0, zSig1, doubleZSig0; - Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) return propagateFloatx80NaNOne(a, status); - if (! aSign) return a; - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (aSign) { - if ((aExp | aSig0) == 0) return a; - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (aExp == 0) { - if (aSig0 == 0) return packFloatx80(0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - } - zExp = ((aExp - 0x3FFF)>>1) + 0x3FFF; - zSig0 = estimateSqrt32(aExp, aSig0>>32); - shift128Right(aSig0, 0, 2 + (aExp & 1), &aSig0, &aSig1); - zSig0 = estimateDiv128To64(aSig0, aSig1, zSig0<<32) + (zSig0<<30); - doubleZSig0 = zSig0<<1; - mul64To128(zSig0, zSig0, &term0, &term1); - sub128(aSig0, aSig1, term0, term1, &rem0, &rem1); - while ((Bit64s) rem0 < 0) { - --zSig0; - doubleZSig0 -= 2; - add128(rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1); - } - zSig1 = estimateDiv128To64(rem1, 0, doubleZSig0); - if ((zSig1 & BX_CONST64(0x3FFFFFFFFFFFFFFF)) <= 5) { - if (zSig1 == 0) zSig1 = 1; - mul64To128(doubleZSig0, zSig1, &term1, &term2); - sub128(rem1, 0, term1, term2, &rem1, &rem2); - mul64To128(zSig1, zSig1, &term2, &term3); - sub192(rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3); - while ((Bit64s) rem1 < 0) { - --zSig1; - shortShift128Left(0, zSig1, 1, &term2, &term3); - term3 |= 1; - term2 |= doubleZSig0; - add192(rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shortShift128Left(0, zSig1, 1, &zSig0, &zSig1); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80(get_float_rounding_precision(status), - 0, zExp, zSig0, zSig1, status); -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128(floatx80 a, struct float_status_t *status) -{ - Bit64u zSig0, zSig1; - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - - if ((aExp == 0x7FFF) && (Bit64u) (aSig<<1)) - return commonNaNToFloat128(floatx80ToCommonNaN(a, status)); - - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - return packFloat128Four(aSign, aExp, zSig0, zSig1); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80(float128 a, struct float_status_t *status) -{ - Bit32s aExp; - Bit64u aSig0, aSig1; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - int aSign = extractFloat128Sign(a); - - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) - return commonNaNToFloatx80(float128ToCommonNaN(a, status)); - - return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) return packFloatx80(aSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - else aSig0 |= BX_CONST64(0x0001000000000000); - - shortShift128Left(aSig0, aSig1, 15, &aSig0, &aSig1); - return roundAndPackFloatx80(80, aSign, aExp, aSig0, aSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point value `a' and quadruple-precision floating point value `b'. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp, zExp; - Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2; - int aSign, bSign, zSign; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - invalid: - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig0 = extractFloat128Frac0(b); - bSig1 = extractFloat128Frac1(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (bSig0 | bSig1))) - { - floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status)); - return propagateFloatx80NaN(a, r, status); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) { - floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b, status)); - return propagateFloatx80NaN(a, r, status); - } - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); - } - return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (aSig == 0) { - if ((bExp == 0) && (bSig0 | bSig1)) float_raise(status, float_flag_denormal); - return packFloatx80(zSign, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - else bSig0 |= BX_CONST64(0x0001000000000000); - - zExp = aExp + bExp - 0x3FFE; - shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1); - mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { - shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); - --zExp; - } - return - roundAndPackFloatx80(get_float_rounding_precision(status), - zSign, zExp, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status) -{ - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - Bit32s expDiff; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - expDiff = aExp - bExp; - - if (0 < expDiff) { - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); - return a; - } - if (bExp == 0) --expDiff; - else bSig0 |= BX_CONST64(0x0001000000000000); - shift128ExtraRightJamming(bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2); - zExp = aExp; - } - else if (expDiff < 0) { - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (aExp == 0) ++expDiff; - else aSig0 |= BX_CONST64(0x0001000000000000); - shift128ExtraRightJamming(aSig0, aSig1, 0, -expDiff, &aSig0, &aSig1, &zSig2); - zExp = bExp; - } - else { - if (aExp == 0x7FFF) { - if (aSig0 | aSig1 | bSig0 | bSig1) - return propagateFloat128NaN(a, b, status); - - return a; - } - add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - if (aExp == 0) return packFloat128Four(zSign, 0, zSig0, zSig1); - zSig2 = 0; - zSig0 |= BX_CONST64(0x0002000000000000); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= BX_CONST64(0x0001000000000000); - add128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - --zExp; - if (zSig0 < BX_CONST64(0x0002000000000000)) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); - roundAndPack: - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs(float128 a, float128 b, int zSign, struct float_status_t *status) -{ - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - Bit32s expDiff; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - - expDiff = aExp - bExp; - shortShift128Left(aSig0, aSig1, 14, &aSig0, &aSig1); - shortShift128Left(bSig0, bSig1, 14, &bSig0, &bSig1); - if (0 < expDiff) goto aExpBigger; - if (expDiff < 0) goto bExpBigger; - if (aExp == 0x7FFF) { - if (aSig0 | aSig1 | bSig0 | bSig1) - return propagateFloat128NaN(a, b, status); - - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - if (aExp == 0) { - aExp = 1; - bExp = 1; - } - if (bSig0 < aSig0) goto aBigger; - if (aSig0 < bSig0) goto bBigger; - if (bSig1 < aSig1) goto aBigger; - if (aSig1 < bSig1) goto bBigger; - return packFloat128(0, 0); - - bExpBigger: - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - return packFloat128Four(zSign ^ 1, 0x7FFF, 0, 0); - } - if (aExp == 0) ++expDiff; - else { - aSig0 |= BX_CONST64(0x4000000000000000); - } - shift128RightJamming(aSig0, aSig1, - expDiff, &aSig0, &aSig1); - bSig0 |= BX_CONST64(0x4000000000000000); - bBigger: - sub128(bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); - return a; - } - if (bExp == 0) --expDiff; - else { - bSig0 |= BX_CONST64(0x4000000000000000); - } - shift128RightJamming(bSig0, bSig1, expDiff, &bSig0, &bSig1); - aSig0 |= BX_CONST64(0x4000000000000000); - aBigger: - sub128(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128(zSign, zExp - 14, zSig0, zSig1, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add(float128 a, float128 b, struct float_status_t *status) -{ - int aSign = extractFloat128Sign(a); - int bSign = extractFloat128Sign(b); - - if (aSign == bSign) { - return addFloat128Sigs(a, b, aSign, status); - } - else { - return subFloat128Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub(float128 a, float128 b, struct float_status_t *status) -{ - int aSign = extractFloat128Sign(a); - int bSign = extractFloat128Sign(b); - - if (aSign == bSign) { - return subFloat128Sigs(a, b, aSign, status); - } - else { - return addFloat128Sigs(a, b, aSign, status); - } -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul(float128 a, float128 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if ((aSig0 | aSig1) || ((bExp == 0x7FFF) && (bSig0 | bSig1))) { - return propagateFloat128NaN(a, b, status); - } - if ((bExp | bSig0 | bSig1) == 0) { - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - if ((aExp | aSig0 | aSig1) == 0) { - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= BX_CONST64(0x0001000000000000); - shortShift128Left(bSig0, bSig1, 16, &bSig0, &bSig1); - mul128To256(aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3); - add128(zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1); - zSig2 |= (zSig3 != 0); - if (BX_CONST64(0x0002000000000000) <= zSig0) { - shift128ExtraRightJamming(zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2); - ++zExp; - } - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div(float128 a, float128 b, struct float_status_t *status) -{ - int aSign, bSign, zSign; - Bit32s aExp, bExp, zExp; - Bit64u aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - Bit64u rem0, rem1, rem2, rem3, term0, term1, term2, term3; - - aSig1 = extractFloat128Frac1(a); - aSig0 = extractFloat128Frac0(a); - aExp = extractFloat128Exp(a); - aSign = extractFloat128Sign(a); - bSig1 = extractFloat128Frac1(b); - bSig0 = extractFloat128Frac0(b); - bExp = extractFloat128Exp(b); - bSign = extractFloat128Sign(b); - - zSign = aSign ^ bSign; - if (aExp == 0x7FFF) { - if (aSig0 | aSig1) return propagateFloat128NaN(a, b, status); - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - if (bExp == 0x7FFF) { - if (bSig0 | bSig1) return propagateFloat128NaN(a, b, status); - return packFloat128Four(zSign, 0, 0, 0); - } - if (bExp == 0) { - if ((bSig0 | bSig1) == 0) { - if ((aExp | aSig0 | aSig1) == 0) { - float_raise(status, float_flag_invalid); - return float128_default_nan; - } - float_raise(status, float_flag_divbyzero); - return packFloat128Four(zSign, 0x7FFF, 0, 0); - } - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1); - } - if (aExp == 0) { - if ((aSig0 | aSig1) == 0) return packFloat128Four(zSign, 0, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat128Subnormal(aSig0, aSig1, &aExp, &aSig0, &aSig1); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | BX_CONST64(0x0001000000000000), aSig1, 15, &aSig0, &aSig1); - shortShift128Left( - bSig0 | BX_CONST64(0x0001000000000000), bSig1, 15, &bSig0, &bSig1); - if (le128(bSig0, bSig1, aSig0, aSig1)) { - shift128Right(aSig0, aSig1, 1, &aSig0, &aSig1); - ++zExp; - } - zSig0 = estimateDiv128To64(aSig0, aSig1, bSig0); - mul128By64To192(bSig0, bSig1, zSig0, &term0, &term1, &term2); - sub192(aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2); - while ((Bit64s) rem0 < 0) { - --zSig0; - add192(rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2); - } - zSig1 = estimateDiv128To64(rem1, rem2, bSig0); - if ((zSig1 & 0x3FFF) <= 4) { - mul128By64To192(bSig0, bSig1, zSig1, &term1, &term2, &term3); - sub192(rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3); - while ((Bit64s) rem1 < 0) { - --zSig1; - add192(rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3); - } - zSig1 |= ((rem1 | rem2 | rem3) != 0); - } - shift128ExtraRightJamming(zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2); - return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the 64-bit two's complement integer `a' to -| the quadruple-precision floating-point format. The conversion is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 int64_to_float128(Bit64s a) -{ - Bit64u zSig0, zSig1; - - if (a == 0) return packFloat128Four(0, 0, 0, 0); - int zSign = (a < 0); - Bit64u absA = zSign ? - a : a; - Bit8u shiftCount = countLeadingZeros64(absA) + 49; - Bit32s zExp = 0x406E - shiftCount; - if (64 <= shiftCount) { - zSig1 = 0; - zSig0 = absA; - shiftCount -= 64; - } - else { - zSig1 = absA; - zSig0 = 0; - } - shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1); - return packFloat128Four(zSign, zExp, zSig0, zSig1); -} - -#endif diff --git a/src/cpu/softfloat/softfloat.h b/src/cpu/softfloat/softfloat.h deleted file mode 100644 index 1d1b0f08f9..0000000000 --- a/src/cpu/softfloat/softfloat.h +++ /dev/null @@ -1,488 +0,0 @@ -/*============================================================================ -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "config.h" /* generated by configure script from config.h.in */ - -#ifndef _SOFTFLOAT_H_ -#define _SOFTFLOAT_H_ - -#define FLOAT16 -#define FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -#ifdef FLOAT16 -typedef Bit16u float16; -#endif -typedef Bit32u float32; -typedef Bit64u float64; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point class. -*----------------------------------------------------------------------------*/ -typedef enum { - float_zero, - float_SNaN, - float_QNaN, - float_negative_inf, - float_positive_inf, - float_denormal, - float_normalized -} float_class_t; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point NaN operands handling mode. -*----------------------------------------------------------------------------*/ -enum float_nan_handling_mode_t { - float_larger_significand_nan = 0, // this mode used by x87 FPU - float_first_operand_nan = 1 // this mode used by SSE -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -enum float_round_t { - float_round_nearest_even = 0, - float_round_down = 1, - float_round_up = 2, - float_round_to_zero = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -enum float_exception_flag_t { - float_flag_invalid = 0x01, - float_flag_denormal = 0x02, - float_flag_divbyzero = 0x04, - float_flag_overflow = 0x08, - float_flag_underflow = 0x10, - float_flag_inexact = 0x20 -}; - -extern const unsigned float_all_exceptions_mask; - -#ifdef FLOATX80 -#define RAISE_SW_C1 0x0200 -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point ordering relations -*----------------------------------------------------------------------------*/ -enum { - float_relation_less = -1, - float_relation_equal = 0, - float_relation_greater = 1, - float_relation_unordered = 2 -}; - -/*---------------------------------------------------------------------------- -| Options to indicate which negations to perform in float*_muladd() -| Using these differs from negating an input or output before calling -| the muladd function in that this means that a NaN doesn't have its -| sign bit inverted before it is propagated. -*----------------------------------------------------------------------------*/ -enum { - float_muladd_negate_c = 1, - float_muladd_negate_product = 2, - float_muladd_negate_result = float_muladd_negate_c | float_muladd_negate_product -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point status structure. -*----------------------------------------------------------------------------*/ -struct float_status_t -{ -#ifdef FLOATX80 - int float_rounding_precision; /* floatx80 only */ -#endif - int float_rounding_mode; - int float_exception_flags; - int float_exception_masks; - int float_suppress_exception; - int float_nan_handling_mode; /* flag register */ - int flush_underflow_to_zero; /* flag register */ - int denormals_are_zeros; /* flag register */ -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE void float_raise(struct float_status_t *status, int flags) -{ - status->float_exception_flags |= flags; -} - -/*---------------------------------------------------------------------------- -| Returns raised IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_exception_flags(const struct float_status_t *status) -{ - return status->float_exception_flags & ~status->float_suppress_exception; -} - -/*---------------------------------------------------------------------------- -| Routine to check if any or all of the software IEC/IEEE floating-point -| exceptions are masked. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int float_exception_masked(const struct float_status_t *status, int flag) -{ - return status->float_exception_masks & flag; -} - -/*---------------------------------------------------------------------------- -| Returns current floating point rounding mode specified by status word. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_float_rounding_mode(const struct float_status_t *status) -{ - return status->float_rounding_mode; -} - -/*---------------------------------------------------------------------------- -| Returns current floating point precision (floatx80 only). -*----------------------------------------------------------------------------*/ - -#ifdef FLOATX80 -BX_CPP_INLINE int get_float_rounding_precision(const struct float_status_t *status) -{ - return status->float_rounding_precision; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns current floating point NaN operands handling mode specified -| by status word. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_float_nan_handling_mode(const struct float_status_t *status) -{ - return status->float_nan_handling_mode; -} - -/*---------------------------------------------------------------------------- -| Raise floating point precision lost up flag (floatx80 only). -*----------------------------------------------------------------------------*/ - -#ifdef FLOATX80 -BX_CPP_INLINE void set_float_rounding_up(struct float_status_t *status) -{ - status->float_exception_flags |= RAISE_SW_C1; -} -#endif - -/*---------------------------------------------------------------------------- -| Returns 1 if the feature is supported; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_denormals_are_zeros(const struct float_status_t *status) -{ - return status->denormals_are_zeros; -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the feature is supported; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -BX_CPP_INLINE int get_flush_underflow_to_zero(const struct float_status_t *status) -{ - return status->flush_underflow_to_zero; -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32(Bit32s, struct float_status_t *status); -float64 int32_to_float64(Bit32s); -float32 int64_to_float32(Bit64s, struct float_status_t *status); -float64 int64_to_float64(Bit64s, struct float_status_t *status); - -float32 uint32_to_float32(Bit32u, struct float_status_t *status); -float64 uint32_to_float64(Bit32u); -float32 uint64_to_float32(Bit64u, struct float_status_t *status); -float64 uint64_to_float64(Bit64u, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -Bit32s float32_to_int32(float32, struct float_status_t *status); -Bit32s float32_to_int32_round_to_zero(float32, struct float_status_t *status); -Bit64s float32_to_int64(float32, struct float_status_t *status); -Bit64s float32_to_int64_round_to_zero(float32, struct float_status_t *status); -Bit32u float32_to_uint32(float32, struct float_status_t *status); -Bit32u float32_to_uint32_round_to_zero(float32, struct float_status_t *status); -Bit64u float32_to_uint64(float32, struct float_status_t *status); -Bit64u float32_to_uint64_round_to_zero(float32, struct float_status_t *status); -float64 float32_to_float64(float32, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int(float32, Bit8u scale, struct float_status_t *status); -float32 float32_add(float32, float32, struct float_status_t *status); -float32 float32_sub(float32, float32, struct float_status_t *status); -float32 float32_mul(float32, float32, struct float_status_t *status); -float32 float32_div(float32, float32, struct float_status_t *status); -float32 float32_sqrt(float32, struct float_status_t *status); -float32 float32_frc(float32, struct float_status_t *status); -float32 float32_muladd(float32, float32, float32, int flags, struct float_status_t *status); -float32 float32_scalef(float32, float32, struct float_status_t *status); -int float32_compare(float32, float32, int quiet, struct float_status_t *status); - -BX_CPP_INLINE float32 float32_round_to_int_one(float32 a, struct float_status_t *status) -{ - return float32_round_to_int(a, 0, status); -} - -BX_CPP_INLINE float32 float32_fmadd(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, 0, status); -} - -BX_CPP_INLINE float32 float32_fmsub(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, float_muladd_negate_c, status); -} - -BX_CPP_INLINE float32 float32_fnmadd(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, float_muladd_negate_product, status); -} - -BX_CPP_INLINE float32 float32_fnmsub(float32 a, float32 b, float32 c, struct float_status_t *status) -{ - return float32_muladd(a, b, c, float_muladd_negate_result, status); -} - -BX_CPP_INLINE int float32_compare_two(float32 a, float32 b, struct float_status_t *status) -{ - return float32_compare(a, b, 0, status); -} - -BX_CPP_INLINE int float32_compare_quiet(float32 a, float32 b, struct float_status_t *status) -{ - return float32_compare(a, b, 1, status); -} - -float_class_t float32_class(float32); - -float32 float32_min(float32 a, float32 b, struct float_status_t *status); -float32 float32_max(float32 a, float32 b, struct float_status_t *status); - -float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status); -float32 float32_getexp(float32 a, struct float_status_t *status); -float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -Bit32s float64_to_int32(float64, struct float_status_t *status); -Bit32s float64_to_int32_round_to_zero(float64, struct float_status_t *status); -Bit64s float64_to_int64(float64, struct float_status_t *status); -Bit64s float64_to_int64_round_to_zero(float64, struct float_status_t *status); -Bit32u float64_to_uint32(float64, struct float_status_t *status); -Bit32u float64_to_uint32_round_to_zero(float64, struct float_status_t *status); -Bit64u float64_to_uint64(float64, struct float_status_t *status); -Bit64u float64_to_uint64_round_to_zero(float64, struct float_status_t *status); -float32 float64_to_float32(float64, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int(float64, Bit8u scale, struct float_status_t *status); -float64 float64_add(float64, float64, struct float_status_t *status); -float64 float64_sub(float64, float64, struct float_status_t *status); -float64 float64_mul(float64, float64, struct float_status_t *status); -float64 float64_div(float64, float64, struct float_status_t *status); -float64 float64_sqrt(float64, struct float_status_t *status); -float64 float64_frc(float64, struct float_status_t *status); -float64 float64_muladd(float64, float64, float64, int flags, struct float_status_t *status); -float64 float64_scalef(float64, float64, struct float_status_t *status); -int float64_compare(float64, float64, int quiet, struct float_status_t *status); - -BX_CPP_INLINE float64 float64_round_to_int_one(float64 a, struct float_status_t *status) -{ - return float64_round_to_int(a, 0, status); -} - -BX_CPP_INLINE float64 float64_fmadd(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, 0, status); -} - -BX_CPP_INLINE float64 float64_fmsub(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, float_muladd_negate_c, status); -} - -BX_CPP_INLINE float64 float64_fnmadd(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, float_muladd_negate_product, status); -} - -BX_CPP_INLINE float64 float64_fnmsub(float64 a, float64 b, float64 c, struct float_status_t *status) -{ - return float64_muladd(a, b, c, float_muladd_negate_result, status); -} - -BX_CPP_INLINE int float64_compare_two(float64 a, float64 b, struct float_status_t *status) -{ - return float64_compare(a, b, 0, status); -} - -BX_CPP_INLINE int float64_compare_quiet(float64 a, float64 b, struct float_status_t *status) -{ - return float64_compare(a, b, 1, status); -} - -float_class_t float64_class(float64); - -float64 float64_min(float64 a, float64 b, struct float_status_t *status); -float64 float64_max(float64 a, float64 b, struct float_status_t *status); - -float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status); -float64 float64_getexp(float64 a, struct float_status_t *status); -float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv); - -#ifdef FLOAT16 -float32 float16_to_float32(float16, struct float_status_t *status); -float16 float32_to_float16(float32, struct float_status_t *status); - -float_class_t float16_class(float16); -#endif - -#ifdef FLOATX80 -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ - -#ifdef BX_BIG_ENDIAN -typedef struct floatx80 { // leave alignment to compiler - Bit16u exp; - Bit64u fraction; -}; floatx80 -#else -typedef struct floatx80 { - Bit64u fraction; - Bit16u exp; -} floatx80; -#endif - -#ifdef __cplusplus -extern "C" { -#endif -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -floatx80 int32_to_floatx80(Bit32s); -floatx80 int64_to_floatx80(Bit64s); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -floatx80 float32_to_floatx80(float32, struct float_status_t *status); -floatx80 float64_to_floatx80(float64, struct float_status_t *status); - -Bit32s floatx80_to_int32(floatx80, struct float_status_t *status); -Bit32s floatx80_to_int32_round_to_zero(floatx80, struct float_status_t *status); -Bit64s floatx80_to_int64(floatx80, struct float_status_t *status); -Bit64s floatx80_to_int64_round_to_zero(floatx80, struct float_status_t *status); - -float32 floatx80_to_float32(floatx80, struct float_status_t *status); -float64 floatx80_to_float64(floatx80, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int(floatx80, struct float_status_t *status); -floatx80 floatx80_add(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_sub(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_mul(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_div(floatx80, floatx80, struct float_status_t *status); -floatx80 floatx80_sqrt(floatx80, struct float_status_t *status); - -float_class_t floatx80_class(floatx80); -#ifdef __cplusplus -} -#endif -#endif /* FLOATX80 */ - -#ifdef FLOAT128 - -#ifdef BX_BIG_ENDIAN -typedef struct float128 { - Bit64u hi, lo; -} float128; -#else -typedef struct float128 { - Bit64u lo, hi; -} float128; -#endif - -#ifdef __cplusplus -extern "C" { -#endif -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -float128 floatx80_to_float128(floatx80 a, struct float_status_t *status); -floatx80 float128_to_floatx80(float128 a, struct float_status_t *status); - -float128 int64_to_float128(Bit64s a); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_add(float128 a, float128 b, struct float_status_t *status); -float128 float128_sub(float128 a, float128 b, struct float_status_t *status); -float128 float128_mul(float128 a, float128 b, struct float_status_t *status); -float128 float128_div(float128 a, float128 b, struct float_status_t *status); -#ifdef __cplusplus -} -#endif -#endif /* FLOAT128 */ - -#endif diff --git a/src/cpu/softfloat/softfloat16.cc b/src/cpu/softfloat/softfloat16.cc deleted file mode 100644 index 8c17d3a86e..0000000000 --- a/src/cpu/softfloat/softfloat16.cc +++ /dev/null @@ -1,129 +0,0 @@ -/*============================================================================ -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Adapted for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include "softfloat.h" - -#ifdef FLOAT16 - -#include "softfloat-round-pack.h" -#include "softfloat-specialize.h" -#include "softfloat-macros.h" - -/*---------------------------------------------------------------------------- -| Determine half-precision floating-point number class -*----------------------------------------------------------------------------*/ - -float_class_t float16_class(float16 a) -{ - Bit16s aExp = extractFloat16Exp(a); - Bit16u aSig = extractFloat16Frac(a); - int aSign = extractFloat16Sign(a); - - if(aExp == 0x1F) { - if (aSig == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & 0x200) ? float_QNaN : float_SNaN; - } - - if(aExp == 0) { - if (aSig == 0) return float_zero; - return float_denormal; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the half-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float16_to_float32(float16 a, struct float_status_t *status) -{ - Bit16u aSig = extractFloat16Frac(a); - Bit16s aExp = extractFloat16Exp(a); - int aSign = extractFloat16Sign(a); - - if (aExp == 0x1F) { - if (aSig) return commonNaNToFloat32(float16ToCommonNaN(a, status)); - return packFloat32(aSign, 0xFF, 0); - } - if (aExp == 0) { - // ignore denormals_are_zeros flag - if (aSig == 0) return packFloat32(aSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloat16Subnormal(aSig, &aExp, &aSig); - --aExp; - } - - return packFloat32(aSign, aExp + 0x70, ((Bit32u) aSig)<<13); -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the half-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float16 float32_to_float16(float32 a, struct float_status_t *status) -{ - Bit32u aSig = extractFloat32Frac(a); - Bit16s aExp = extractFloat32Exp(a); - int aSign = extractFloat32Sign(a); - - if (aExp == 0xFF) { - if (aSig) return commonNaNToFloat16(float32ToCommonNaN(a, status)); - return packFloat16(aSign, 0x1F, 0); - } - if (aExp == 0) { - if (get_denormals_are_zeros(status)) aSig = 0; - if (aSig == 0) return packFloat16(aSign, 0, 0); - float_raise(status, float_flag_denormal); - } - - aSig = shift32RightJamming(aSig, 9); - Bit16u zSig = (Bit16u) aSig; - if (aExp || zSig) { - zSig |= 0x4000; - aExp -= 0x71; - } - - return roundAndPackFloat16(aSign, aExp, zSig, status); -} - -#endif diff --git a/src/cpu/softfloat/softfloatx80.cc b/src/cpu/softfloat/softfloatx80.cc deleted file mode 100644 index fc24096011..0000000000 --- a/src/cpu/softfloat/softfloatx80.cc +++ /dev/null @@ -1,384 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#include -#include -#include <86box/86box.h> -#include "../cpu.h" - -#include "softfloatx80.h" -#include "softfloat-round-pack.h" -#include "softfloat-macros.h" - -const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); -const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); -const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); -const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe)); -const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc)); -const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); -const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799)); -const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac)); -const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000)); - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -const float32 float32_negative_inf = 0xff800000; -const float32 float32_positive_inf = 0x7f800000; -const float32 float32_negative_zero = 0x80000000; -const float32 float32_positive_zero = 0x00000000; -const float32 float32_negative_one = 0xbf800000; -const float32 float32_positive_one = 0x3f800000; -const float32 float32_max_float = 0x7f7fffff; -const float32 float32_min_float = 0xff7fffff; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -const float32 float32_default_nan = 0xffc00000; - -/*---------------------------------------------------------------------------- -| Commonly used single-precision floating point constants -*----------------------------------------------------------------------------*/ -const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000); -const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000); -const float64 float64_negative_zero = BX_CONST64(0x8000000000000000); -const float64 float64_positive_zero = BX_CONST64(0x0000000000000000); -const float64 float64_negative_one = BX_CONST64(0xbff0000000000000); -const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000); -const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff); -const float64 float64_min_float = BX_CONST64(0xffefffffffffffff); - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000); - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic - which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN or the -| conversion overflows, the integer indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit16s floatx80_to_int16(floatx80 a, struct float_status_t *status) -{ - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); - return int16_indefinite; - } - - Bit32s v32 = floatx80_to_int32(a, status); - - if ((v32 > 32767) || (v32 < -32768)) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return int16_indefinite; - } - - return (Bit16s) v32; -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 16-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN or the conversion overflows, the integer -| indefinite value is returned. -*----------------------------------------------------------------------------*/ - -Bit16s floatx80_to_int16_round_to_zero(floatx80 a, struct float_status_t *status) -{ - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); - return int16_indefinite; - } - - Bit32s v32 = floatx80_to_int32_round_to_zero(a, status); - - if ((v32 > 32767) || (v32 < -32768)) { - status->float_exception_flags = float_flag_invalid; // throw away other flags - return int16_indefinite; - } - - return (Bit16s) v32; -} - -/*---------------------------------------------------------------------------- -| Separate the source extended double-precision floating point value `a' -| into its exponent and significand, store the significant back to the -| 'a' and return the exponent. The operation performed is a superset of -| the IEC/IEEE recommended logb(x) function. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit64u aSig = extractFloatx80Frac(*a); - Bit32s aExp = extractFloatx80Exp(*a); - int aSign = extractFloatx80Sign(*a); - - if (floatx80_is_unsupported(*a)) - { - float_raise(status, float_flag_invalid); - *a = floatx80_default_nan; - return *a; - } - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - { - *a = propagateFloatx80NaNOne(*a, status); - return *a; - } - return packFloatx80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) - { - if (aSig == 0) { - float_raise(status, float_flag_divbyzero); - *a = packFloatx80(aSign, 0, 0); - return packFloatx80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - } - - a->exp = (aSign << 15) + 0x3FFF; - a->fraction = aSig; - return int32_to_floatx80(aExp - 0x3FFF); -} - -/*---------------------------------------------------------------------------- -| Scales extended double-precision floating-point value in operand `a' by -| value `b'. The function truncates the value in the second operand 'b' to -| an integral value and adds that value to the exponent of the operand 'a'. -| The operation performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status) -{ -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. -*----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - Bit32s aExp, bExp; - Bit64u aSig, bSig; - - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); - - if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); - } - if ((bExp == 0x7FFF) && bSign) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - return a; - } - if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if ((aExp | aSig) == 0) { - if (! bSign) { - float_raise(status, float_flag_invalid); - return floatx80_default_nan; - } - return a; - } - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); - if (bSign) return packFloatx80(aSign, 0, 0); - return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000)); - } - if (aExp == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); - if (aSig == 0) return a; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - if (bExp < 0x3FFF) - return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0, status); - } - if (bExp == 0) { - if (bSig == 0) return a; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - } - - if (bExp > 0x400E) { - /* generate appropriate overflow/underflow */ - return roundAndPackFloatx80(80, aSign, - bSign ? -0x3FFF : 0x7FFF, aSig, 0, status); - } - - if (bExp < 0x3FFF) return a; - - int shiftCount = 0x403E - bExp; - bSig >>= shiftCount; - Bit32s scale = (Bit32s) bSig; - if (bSign) scale = -scale; /* -32768..32767 */ - return - roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0, status); -} - -/*---------------------------------------------------------------------------- -| Determine extended-precision floating-point number class. -*----------------------------------------------------------------------------*/ - -float_class_t floatx80_class(floatx80 a) -{ - Bit32s aExp = extractFloatx80Exp(a); - Bit64u aSig = extractFloatx80Frac(a); - - if(aExp == 0) { - if (aSig == 0) - return float_zero; - - /* denormal or pseudo-denormal */ - return float_denormal; - } - - /* valid numbers have the MS bit set */ - if (!(aSig & BX_CONST64(0x8000000000000000))) - return float_SNaN; /* report unsupported as SNaNs */ - - if(aExp == 0x7fff) { - int aSign = extractFloatx80Sign(a); - - if (((Bit64u) (aSig<< 1)) == 0) - return (aSign) ? float_negative_inf : float_positive_inf; - - return (aSig & BX_CONST64(0x4000000000000000)) ? float_QNaN : float_SNaN; - } - - return float_normalized; -} - -/*---------------------------------------------------------------------------- -| Compare between two extended precision floating point numbers. Returns -| 'float_relation_equal' if the operands are equal, 'float_relation_less' if -| the value 'a' is less than the corresponding value `b', -| 'float_relation_greater' if the value 'a' is greater than the corresponding -| value `b', or 'float_relation_unordered' otherwise. -*----------------------------------------------------------------------------*/ - -int floatx80_compare(floatx80 a, floatx80 b, int quiet, struct float_status_t *status) -{ - float_class_t aClass = floatx80_class(a); - float_class_t bClass = floatx80_class(b); - - if (fpu_type < FPU_287XL) { - if ((aClass == float_positive_inf) && (bClass == float_negative_inf)) - { - return float_relation_equal; - } - - if ((aClass == float_negative_inf) && (bClass == float_positive_inf)) - { - return float_relation_equal; - } - } - - if (aClass == float_SNaN || bClass == float_SNaN) - { - /* unsupported reported as SNaN */ - float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_QNaN || bClass == float_QNaN) { - if (! quiet) float_raise(status, float_flag_invalid); - return float_relation_unordered; - } - - if (aClass == float_denormal || bClass == float_denormal) { - float_raise(status, float_flag_denormal); - } - - int aSign = extractFloatx80Sign(a); - int bSign = extractFloatx80Sign(b); - - if (aClass == float_zero) { - if (bClass == float_zero) return float_relation_equal; - return bSign ? float_relation_greater : float_relation_less; - } - - if (bClass == float_zero || aSign != bSign) { - return aSign ? float_relation_less : float_relation_greater; - } - - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - - if (aClass == float_denormal) - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); - - if (bClass == float_denormal) - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); - - if (aExp == bExp && aSig == bSig) - return float_relation_equal; - - int less_than = - aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig))) - : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig))); - - if (less_than) return float_relation_less; - return float_relation_greater; -} - - -int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status) -{ - return floatx80_compare(a, b, 0, status); -} - -int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status) -{ - return floatx80_compare(a, b, 1, status); -} diff --git a/src/cpu/softfloat/softfloatx80.h b/src/cpu/softfloat/softfloatx80.h deleted file mode 100644 index 1f96141b4c..0000000000 --- a/src/cpu/softfloat/softfloatx80.h +++ /dev/null @@ -1,121 +0,0 @@ -/*============================================================================ -This source file is an extension to the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator) -floating point emulation. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. -=============================================================================*/ - -/*============================================================================ - * Written for Bochs (x86 achitecture simulator) by - * Stanislav Shwartsman [sshwarts at sourceforge net] - * ==========================================================================*/ - -#ifndef _SOFTFLOATX80_EXTENSIONS_H_ -#define _SOFTFLOATX80_EXTENSIONS_H_ - -#include "softfloat.h" -#include "softfloat-specialize.h" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -extern "C" { -#endif - -Bit16s floatx80_to_int16(floatx80, struct float_status_t *status); -Bit16s floatx80_to_int16_round_to_zero(floatx80, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status); -floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status); -int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status); -int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status); -floatx80 f2xm1(floatx80 a, struct float_status_t *status); -floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status); -floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status); -floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision trigonometric functions. -*----------------------------------------------------------------------------*/ - -int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status); -int fsin(floatx80 *a, struct float_status_t *status); -int fcos(floatx80 *a, struct float_status_t *status); -int ftan(floatx80 *a, struct float_status_t *status); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision compare. -*----------------------------------------------------------------------------*/ - -int floatx80_compare(floatx80, floatx80, int quiet, struct float_status_t *status); -int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status); -int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status); - -#ifdef __cplusplus -} -#endif - -/*----------------------------------------------------------------------------- -| Calculates the absolute value of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -BX_CPP_INLINE floatx80& floatx80_abs(floatx80 ®) -#else -BX_CPP_INLINE floatx80 floatx80_abs(floatx80 reg) -#endif -{ - reg.exp &= 0x7FFF; - return reg; -} - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -#ifdef __cplusplus -BX_CPP_INLINE floatx80& floatx80_chs(floatx80 ®) -#else -BX_CPP_INLINE floatx80 floatx80_chs(floatx80 reg) -#endif -{ - reg.exp ^= 0x8000; - return reg; -} - -/*----------------------------------------------------------------------------- -| Commonly used extended double-precision floating-point constants. -*----------------------------------------------------------------------------*/ - -extern const floatx80 Const_Z; -extern const floatx80 Const_1; -extern const floatx80 Const_L2T; -extern const floatx80 Const_L2E; -extern const floatx80 Const_PI; -extern const floatx80 Const_LG2; -extern const floatx80 Const_LN2; -extern const floatx80 Const_INF; -#endif diff --git a/src/cpu/softfloat3e/CMakeLists.txt b/src/cpu/softfloat3e/CMakeLists.txt new file mode 100644 index 0000000000..9f9ae06792 --- /dev/null +++ b/src/cpu/softfloat3e/CMakeLists.txt @@ -0,0 +1,57 @@ +# +# 86Box A hypervisor and IBM PC system emulator that specializes in +# running old operating systems and software designed for IBM +# PC systems and compatibles from 1981 through fairly recent +# system designs based on the PCI bus. +# +# This file is part of the 86Box distribution. +# +# CMake build script. +# +# Authors: David Hrdlička, +# +# Copyright 2020-2021 David Hrdlička. +# + +add_library(softfloat3e OBJECT primitives.c softfloat-specialize.c + extF80_addsub.cc extF80_class.cc extF80_compare.cc + extF80_div.cc extF80_extract.cc extF80_mul.cc extF80_rem.cc extF80_roundToInt.cc + extF80_scale.cc extF80_sqrt.cc extF80_to_f16.cc extF80_to_f32.cc extF80_to_f64.cc + extF80_to_f128.cc extF80_to_i32.cc extF80_to_i32_r_minMag.cc extF80_to_i64.cc + extF80_to_i64_r_minMag.cc extF80_to_ui32.cc extF80_to_ui32_r_minMag.cc extF80_to_ui64.cc + extF80_to_ui64_r_minMag.cc f16_addsub.c f16_class.c f16_compare.c f16_div.c f16_getExp.c + f16_getMant.c f16_minmax.c f16_mul.c f16_mulAdd.c f16_range.c f16_roundToInt.c + f16_sqrt.c f16_to_extF80.cc f16_to_f32.c f16_to_f64.c f16_to_i32.c f16_to_i32_r_minMag.c + f16_to_i64.c f16_to_i64_r_minMag.c f16_to_ui32.c f16_to_ui32_r_minMag.c f16_to_ui64.c + f16_to_ui64_r_minMag.c f32_addsub.c f32_class.c f32_compare.c f32_div.c f32_frc.c + f32_getExp.c f32_getMant.c f32_minmax.c f32_mul.c f32_mulAdd.c f32_range.c + f32_roundToInt.c f32_scalef.c f32_sqrt.c f32_to_extF80.cc f32_to_f16.c f32_to_f64.c + f32_to_f128.cc f32_to_i32.c f32_to_i32_r_minMag.c f32_to_i64.c f32_to_i64_r_minMag.c + f32_to_ui32.c f32_to_ui32_r_minMag.c f32_to_ui64.c f32_to_ui64_r_minMag.c f64_addsub.c + f64_class.c f64_compare.c f64_div.c f64_frc.c f64_getExp.c f64_getMant.c f64_minmax.c + f64_mul.c f64_mulAdd.c f64_range.c f64_roundToInt.c f64_scalef.c f64_sqrt.c f64_to_extF80.cc + f64_to_f16.c f64_to_f32.c f64_to_f128.cc f64_to_i32.c f64_to_i32_r_minMag.c f64_to_i64.c + f64_to_i64_r_minMag.c f64_to_ui32.c f64_to_ui32_r_minMag.c f64_to_ui64.c f64_to_ui64_r_minMag.c + f128_addsub.cc f128_div.cc f128_mul.cc f128_mulAdd.cc f128_roundToInt.cc f128_to_extF80.cc + f128_to_f32.cc f128_to_f64.cc f128_to_i32.cc f128_to_i32_r_minMag.cc f128_to_i64.cc + f128_to_i64_r_minMag.cc f128_to_ui32.cc f128_to_ui32_r_minMag.cc f128_to_ui64.cc + f128_to_ui64_r_minMag.cc i32_to_extF80.cc i32_to_f16.c i32_to_f32.c i32_to_f64.c + i32_to_f128.cc i64_to_extF80.cc i64_to_f16.c i64_to_f32.c i64_to_f64.c i64_to_f128.cc + isNaN.cc isSignalingNaN.cc s_add128.cc s_add256M.c s_addMagsExtF80.cc s_addMagsF16.c + s_addMagsF32.c s_addMagsF64.c s_addMagsF128.cc s_approxRecip_1Ks.c s_approxRecipSqrt_1Ks.c + s_approxRecipSqrt32_1.c s_commonNaNToExtF80UI.cc s_commonNaNToF16UI.c s_commonNaNToF32UI.c + s_commonNaNToF64UI.c s_commonNaNToF128UI.cc s_countLeadingZeros8.c s_countLeadingZeros16.c + s_countLeadingZeros32.c s_countLeadingZeros64.c s_eq128.c s_le128.c s_lt128.c + s_mul64ByShifted32To128.cc s_mul64To128.cc s_mul128By32.cc s_mul128To256M.cc + s_normRoundPackToExtF80.cc s_normRoundPackToF16.c s_normRoundPackToF32.c s_normRoundPackToF64.c + s_normRoundPackToF128.cc s_normSubnormalExtF80Sig.cc s_normSubnormalF16Sig.c + s_normSubnormalF32Sig.c s_normSubnormalF64Sig.c s_normSubnormalF128Sig.cc s_packToExtF80.cc + s_propagateNaNExtF80UI.cc s_propagateNaNF16UI.c s_propagateNaNF32UI.c s_propagateNaNF64UI.c + s_propagateNaNF128UI.cc s_roundPackToExtF80.cc s_roundPackToF16.c s_roundPackToF32.c + s_roundPackToF64.c s_roundPackToF128.cc s_roundToI32.c s_roundToI64.c s_roundToUI32.c + s_roundToUI64.c s_shiftRightJam32.c s_shiftRightJam64.c s_shiftRightJam64Extra.c + s_shiftRightJam256M.c s_shortShiftLeft128.cc s_shortShiftRight128.cc s_shortShiftRightJam64.c + s_shortShiftRightJam64Extra.c s_sub128.cc s_sub256M.c s_subMagsExtF80.cc s_subMagsF16.c + s_subMagsF32.c s_subMagsF64.c s_subMagsF128.cc ui32_to_extF80.cc ui32_to_f16.c ui32_to_f32.c + ui32_to_f64.c ui32_to_f128.cc ui64_to_extF80.cc ui64_to_f16.c ui64_to_f32.c ui64_to_f64.c + ui64_to_f128.cc f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc poly.cc consts.cc) \ No newline at end of file diff --git a/src/cpu/softfloat3e/COPYING.txt b/src/cpu/softfloat3e/COPYING.txt new file mode 100644 index 0000000000..b5690face0 --- /dev/null +++ b/src/cpu/softfloat3e/COPYING.txt @@ -0,0 +1,37 @@ + +License for Berkeley SoftFloat Release 3e + +John R. Hauser +2018 January 20 + +The following applies to the whole of SoftFloat Release 3e as well as to +each source file individually. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/src/cpu/softfloat3e/README.html b/src/cpu/softfloat3e/README.html new file mode 100644 index 0000000000..e695c2bd82 --- /dev/null +++ b/src/cpu/softfloat3e/README.html @@ -0,0 +1,49 @@ + + + + +Berkeley SoftFloat Package Overview + + + + +

Package Overview for Berkeley SoftFloat Release 3e

+ +

+John R. Hauser
+2018 January 20
+

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +SoftFloat is distributed in the form of C source code. +Building the SoftFloat sources generates a library file (typically +softfloat.a or libsoftfloat.a) containing the +floating-point subroutines. +

+ +

+The SoftFloat package is documented in the following files in the +doc subdirectory: +

+ + + + + + + + + + + + + +
SoftFloat.htmlDocumentation for using the SoftFloat functions.
SoftFloat-source.htmlDocumentation for building SoftFloat.
SoftFloat-history.html   History of the major changes to SoftFloat.
+
+Other files in the package comprise the source code for SoftFloat. +

+ + + diff --git a/src/cpu/softfloat3e/README.txt b/src/cpu/softfloat3e/README.txt new file mode 100644 index 0000000000..1613c76718 --- /dev/null +++ b/src/cpu/softfloat3e/README.txt @@ -0,0 +1,21 @@ + +Package Overview for Berkeley SoftFloat Release 3e + +John R. Hauser +2018 January 20 + +Berkeley SoftFloat is a software implementation of binary floating-point +that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat +is distributed in the form of C source code. Building the SoftFloat sources +generates a library file (typically "softfloat.a" or "libsoftfloat.a") +containing the floating-point subroutines. + +The SoftFloat package is documented in the following files in the "doc" +subdirectory: + + SoftFloat.html Documentation for using the SoftFloat functions. + SoftFloat-source.html Documentation for building SoftFloat. + SoftFloat-history.html History of the major changes to SoftFloat. + +Other files in the package comprise the source code for SoftFloat. + diff --git a/src/cpu/softfloat3e/config.h b/src/cpu/softfloat3e/config.h new file mode 100644 index 0000000000..9febce2424 --- /dev/null +++ b/src/cpu/softfloat3e/config.h @@ -0,0 +1,14 @@ +#ifndef EMU_SF_CONFIG_H +#define EMU_SF_CONFIG_H + +/*---------------------------------------------------------------------------- +| The `LIT64' macro takes as its argument a textual integer literal and +| if necessary ``marks'' the literal as having a 64-bit integer type. +| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be +| appended with the letters `LL' standing for `long long', which is `gcc's +| name for the 64-bit integer type. Some compilers may allow `LIT64' to be +| defined as the identity macro: `#define LIT64( a ) a'. +*----------------------------------------------------------------------------*/ +#define BX_CONST64(a) a##LL + +#endif /*EMU_SF_CONFIG_H*/ diff --git a/src/cpu/softfloat3e/consts.cc b/src/cpu/softfloat3e/consts.cc new file mode 100644 index 0000000000..235a039965 --- /dev/null +++ b/src/cpu/softfloat3e/consts.cc @@ -0,0 +1,51 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include <86box/86box.h> +#include "../cpu.h" + +#include "softfloat-specialize.h" + +const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); +const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); +const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe)); +const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc)); +const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); +const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799)); +const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac)); +const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000)); diff --git a/src/cpu/softfloat3e/doc/SoftFloat-history.html b/src/cpu/softfloat3e/doc/SoftFloat-history.html new file mode 100644 index 0000000000..d81c6bc5a2 --- /dev/null +++ b/src/cpu/softfloat3e/doc/SoftFloat-history.html @@ -0,0 +1,258 @@ + + + + +Berkeley SoftFloat History + + + + +

History of Berkeley SoftFloat, to Release 3e

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Release 3e (2018 January)

+ +
    + +
  • +Changed the default numeric code for optional rounding mode odd +(round to odd, also known as jamming) from 5 to 6. + +
  • +Modified the behavior of rounding mode odd when rounding to an +integer value (either conversion to an integer format or a +‘roundToInt’ function). +Previously, for those cases only, rounding mode odd acted the same +as rounding to minimum magnitude. +Now all operations are rounded consistently. + +
  • +Fixed some errors in the specialization code modeling Intel x86 floating-point, +specifically the integers returned on invalid operations and the propagation of +NaN payloads in a few rare cases. + +
  • +Added specialization code modeling ARM floating-point, conforming to VFPv2 or +later. + +
  • +Added an example target for ARM processors. + +
  • +Fixed a minor bug whereby function f16_to_ui64 might return a +different integer than expected in the case that the floating-point operand is +negative. + +
  • +Added example target-specific optimization for GCC, employing GCC instrinsics +and support for 128-bit integer arithmetic. + +
  • +Made other minor improvements. + +
+ + +

Release 3d (2017 August)

+ +
    + +
  • +Fixed bugs in the square root functions for 64-bit +double-precision, 80-bit double-extended-precision, and +128-bit quadruple-precision. +For 64-bit double-precision (f64_sqrt), the result +could sometimes be off by 1 unit in the last place +(1 ulp) from what it should be. +For the larger formats, the square root could be wrong in a large portion of +the less-significant bits. +(A bug in f128_sqrt was first reported by Alexei Sibidanov.) + +
+ + +

Release 3c (2017 February)

+ +
    + +
  • +Added optional rounding mode odd (round to odd, also known as +jamming). + +
  • +Corrected the documentation concerning non-canonical representations in +80-bit double-extended-precision. + +
+ + +

Release 3b (2016 July)

+ +
    + +
  • +Implemented the common 16-bit “half-precision” +floating-point format (float16_t). + +
  • +Made the integer values returned on invalid conversions to integer formats +be determined by the port-specific specialization instead of being the same for +all ports. + +
  • +Added preprocessor macro THREAD_LOCAL to allow the floating-point +state (modes and exception flags) to be made per-thread. + +
  • +Modified the provided Makefiles to allow some options to be overridden from the +make command. + +
  • +Made other minor improvements. + +
+ + +

Release 3a (2015 October)

+ +
    + +
  • +Replaced the license text supplied by the University of California, Berkeley. + +
+ + +

Release 3 (2015 February)

+ +
    + +
  • +Complete rewrite, funded by the University of California, Berkeley, and +consequently having a different use license than earlier releases. +Major changes included renaming most types and functions, upgrading some +algorithms, restructuring the source files, and making SoftFloat into a true +library. + +
  • +Added functions to convert between floating-point and unsigned integers, both +32-bit and 64-bit (uint32_t and +uint64_t). + +
  • +Added functions for fused multiply-add, for all supported floating-point +formats except 80-bit double-extended-precision. + +
  • +Added support for a fifth rounding mode, near_maxMag (round to +nearest, with ties to maximum magnitude, away from zero). + +
  • +Dropped the timesoftfloat program (now part of the Berkeley +TestFloat package). + +
+ + +

Release 2c (2015 January)

+ +
    + +
  • +Fixed mistakes affecting some 64-bit processors. + +
  • +Further improved the documentation and the wording for the legal restrictions +on using SoftFloat releases through 2c (not applicable to +Release 3 or later). + +
+ + +

Release 2b (2002 May)

+ +
    + +
  • +Made minor updates to the documentation, including improved wording for the +legal restrictions on using SoftFloat. + +
+ + +

Release 2a (1998 December)

+ +
    + +
  • +Added functions to convert between 64-bit integers +(int64) and all supported floating-point formats. + +
  • +Fixed a bug in all 64-bit-version square root functions except +float32_sqrt that caused the result sometimes to be off by +1 unit in the last place (1 ulp) from what it should +be. +(Bug discovered by Paul Donahue.) + +
  • +Improved the Makefiles. +
+ + +

Release 2 (1997 June)

+ +
    + +
  • +Created the 64-bit (bits64) version, adding the +floatx80 and float128 formats. + +
  • +Changed the source directory structure, splitting the sources into a +bits32 and a bits64 version. +Renamed environment.h to milieu.h to avoid confusion +with environment variables. + +
  • +Fixed a small error that caused float64_round_to_int often to +round the wrong way in nearest/even mode when the operand was between +220 and 221 and halfway between two integers. + +
+ + +

Release 1a (1996 July)

+ +
    + +
  • +Corrected a mistake that caused borderline underflow cases not to raise the +underflow flag when they should have. +(Problem reported by Doug Priest.) + +
  • +Added the float_detect_tininess variable to control whether +tininess is detected before or after rounding. + +
+ + +

Release 1 (1996 July)

+ +
    + +
  • +Original release, based on work done for the International Computer Science +Institute (ICSI) in Berkeley, California. + +
+ + + + diff --git a/src/cpu/softfloat3e/doc/SoftFloat-source.html b/src/cpu/softfloat3e/doc/SoftFloat-source.html new file mode 100644 index 0000000000..4ff9d4c45a --- /dev/null +++ b/src/cpu/softfloat3e/doc/SoftFloat-source.html @@ -0,0 +1,686 @@ + + + + +Berkeley SoftFloat Source Documentation + + + + +

Berkeley SoftFloat Release 3e: Source Documentation

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. SoftFloat Package Directory Structure
5. Issues for Porting SoftFloat to a New Target
5.1. Standard Headers <stdbool.h> and + <stdint.h>
5.2. Specializing Floating-Point Behavior
5.3. Macros for Build Options
5.4. Adapting a Template Target Directory
5.5. Target-Specific Optimization of Primitive Functions
6. Testing SoftFloat
7. Providing SoftFloat as a Common Library for Applications
8. Contact Information
+
+ + +

1. Introduction

+ +

+This document gives information needed for compiling and/or porting Berkeley +SoftFloat, a library of C functions implementing binary floating-point +conforming to the IEEE Standard for Floating-Point Arithmetic. +For basic documentation about SoftFloat refer to +SoftFloat.html. +

+ +

+The source code for SoftFloat is intended to be relatively machine-independent +and should be compilable with any ISO-Standard C compiler that also supports +64-bit integers. +SoftFloat has been successfully compiled with the GNU C Compiler +(gcc) for several platforms. +

+ +

+Release 3 of SoftFloat was a complete rewrite relative to +Release 2 or earlier. +Changes to the interface of SoftFloat functions are documented in +SoftFloat.html. +The current version of SoftFloat is Release 3e. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of either 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+C Standard header files <stdbool.h> and +<stdint.h> are required for defining standard Boolean and +integer types. +If these headers are not supplied with the C compiler, minimal substitutes must +be provided. +SoftFloat’s dependence on these headers is detailed later in +section 5.1, Standard Headers <stdbool.h> +and <stdint.h>. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (now through 3e) was +done in the employ of the University of California, Berkeley, within the +Department of Electrical Engineering and Computer Sciences, first for the +Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3e as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. +All rights reserved. +

+ +

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +

    + +
  1. +

    +Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. +

    + +
  2. +

    +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions, and the following disclaimer in the documentation and/or +other materials provided with the distribution. +

    + +
  3. +

    +Neither the name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. +

    + +
+

+ +

+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +

+ + +

4. SoftFloat Package Directory Structure

+ +

+Because SoftFloat is targeted to multiple platforms, its source code is +slightly scattered between target-specific and target-independent directories +and files. +The supplied directory structure is as follows: +

+
+doc
+source
+    include
+    8086
+    8086-SSE
+    ARM-VFPv2
+    ARM-VFPv2-defaultNaN
+build
+    template-FAST_INT64
+    template-not-FAST_INT64
+    Linux-386-GCC
+    Linux-386-SSE2-GCC
+    Linux-x86_64-GCC
+    Linux-ARM-VFPv2-GCC
+    Win32-MinGW
+    Win32-SSE2-MinGW
+    Win64-MinGW-w64
+
+
+The majority of the SoftFloat sources are provided in the source +directory. +The include subdirectory contains several header files +(unsurprisingly), while the other subdirectories of source contain +source files that specialize the floating-point behavior to match particular +processor families: +
+
+
8086
+
+Intel’s older, 8087-derived floating-point, extended to all supported +floating-point types +
+
8086-SSE
+
+Intel’s x86 processors with Streaming SIMD Extensions (SSE) and later +compatible extensions, having 8087 behavior for 80-bit +double-extended-precision (extFloat80_t) and SSE behavior for +other floating-point types +
+
ARM-VFPv2
+
+ARM’s VFPv2 or later floating-point, with NaN payload propagation +
+
ARM-VFPv2-defaultNaN
+
+ARM’s VFPv2 or later floating-point, with the “default NaN” +option +
+
+
+If other specializations are attempted, these would be expected to be other +subdirectories of source alongside the ones listed above. +Specialization is covered later, in section 5.2, Specializing +Floating-Point Behavior. +

+ +

+The build directory is intended to contain a subdirectory for each +target platform for which a build of the SoftFloat library may be created. +For each build target, the target’s subdirectory is where all derived +object files and the completed SoftFloat library (typically +softfloat.a or libsoftfloat.a) are created. +The two template subdirectories are not actual build targets but +contain sample files for creating new target directories. +(The meaning of FAST_INT64 will be explained later.) +

+ +

+Ignoring the template directories, the supplied target directories +are intended to follow a naming system of +<execution-environment>-<compiler>. +For the example targets, +<execution-environment> is +Linux-386, Linux-386-SSE2, +Linux-x86_64, +Linux-ARM-VFPv2, Win32, +Win32-SSE2, or Win64, and +<compiler> is GCC, +MinGW, or MinGW-w64. +

+ +

+All of the supplied target directories are merely examples that may or may not +be correct for compiling on any particular system. +Despite requests, there are currently no plans to include and maintain in the +SoftFloat package the build files needed for a great many users’ +compilation environments, which can span a huge range of operating systems, +compilers, and other tools. +

+ +

+As supplied, each target directory contains two files: +

+
+Makefile
+platform.h
+
+
+The provided Makefile is written for GNU make. +A build of SoftFloat for the specific target is begun by executing the +make command with the target directory as the current directory. +A completely different build tool can be used if an appropriate +Makefile equivalent is created. +

+ +

+The platform.h header file exists to provide a location for +additional C declarations specific to the build target. +Every C source file of SoftFloat contains a #include for +platform.h. +In many cases, the contents of platform.h can be as simple as one +or two lines of code. +At the other extreme, to get maximal performance from SoftFloat, it may be +desirable to include in header platform.h (directly or via +#include) declarations for numerous target-specific optimizations. +Such possibilities are discussed in the next section, Issues for Porting +SoftFloat to a New Target. +If the target’s compiler or library has bugs or other shortcomings, +workarounds for these issues may also be possible with target-specific +declarations in platform.h, avoiding the need to modify the main +SoftFloat sources. +

+ + +

5. Issues for Porting SoftFloat to a New Target

+ +

5.1. Standard Headers <stdbool.h> and <stdint.h>

+ +

+The SoftFloat sources make use of standard headers +<stdbool.h> and <stdint.h>, which have +been part of the ISO C Standard Library since 1999. +With any recent compiler, these standard headers are likely to be supported, +even if the compiler does not claim complete conformance to the latest ISO C +Standard. +For older or nonstandard compilers, substitutes for +<stdbool.h> and <stdint.h> may need to be +created. +SoftFloat depends on these names from <stdbool.h>: +

+
+bool
+true
+false
+
+
+and on these names from <stdint.h>: +
+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+UINT64_C
+INT64_C
+uint_least8_t
+uint_fast8_t
+uint_fast16_t
+uint_fast32_t
+uint_fast64_t
+int_fast8_t
+int_fast16_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

5.2. Specializing Floating-Point Behavior

+ +

+The IEEE Floating-Point Standard allows for some flexibility in a conforming +implementation, particularly concerning NaNs. +The SoftFloat source directory is supplied with some +specialization subdirectories containing possible definitions for this +implementation-specific behavior. +For example, the 8086 and 8086-SSE +subdirectories have source files that specialize SoftFloat’s behavior to +match that of Intel’s x86 line of processors. +The files in a specialization subdirectory must determine: +

    +
  • +whether tininess for underflow is detected before or after rounding by default; +
  • +how signaling NaNs are distinguished from quiet NaNs; +
  • +what (if anything) special happens when exceptions are raised; +
  • +the default generated quiet NaNs; +
  • +how NaNs are propagated from function inputs to output; and +
  • +the integer results returned when conversions to integer type raise the +invalid exception. +
+

+ +

+As provided, the build process for a target expects to involve exactly +one specialization directory that defines all of these +implementation-specific details for the target. +A specialization directory such as 8086 is expected to contain a +header file called specialize.h, together with whatever other +source files are needed to complete the specialization. +

+ +

+A new build target may use an existing specialization, such as the ones +provided by the 8086 and 8086-SSE +subdirectories. +If a build target needs a new specialization, different from any existing ones, +it is recommended that a new specialization directory be created for this +purpose. +The specialize.h header file from any of the provided +specialization subdirectories can be used as a model for what definitions are +needed. +

+ + +

5.3. Macros for Build Options

+ +

+The SoftFloat source files adapt the floating-point implementation according to +several C preprocessor macros: +

+
+
LITTLEENDIAN +
+Must be defined for little-endian machines; must not be defined for big-endian +machines. +
INLINE +
+Specifies the sequence of tokens used to indicate that a C function should be +inlined. +If macro INLINE_LEVEL is defined with a value of 1 or higher, this +macro must be defined; otherwise, this macro is ignored and need not be +defined. +For compilers that conform to the C Standard’s rules for inline +functions, this macro can be defined as the single keyword inline. +For other compilers that follow a convention pre-dating the standardization of +inline, this macro may need to be defined to extern +inline. +
THREAD_LOCAL +
+Can be defined to a sequence of tokens that, when appearing at the start of a +variable declaration, indicates to the C compiler that the variable is +per-thread, meaning that each execution thread gets its own separate +instance of the variable. +This macro is used in header softfloat.h in the declarations of +variables softfloat_roundingMode, +softfloat_detectTininess, extF80_roundingPrecision, +and softfloat_exceptionFlags. +If macro THREAD_LOCAL is left undefined, these variables will +default to being ordinary global variables. +Depending on the compiler, possible valid definitions of this macro include +_Thread_local and __thread. +
+
+
SOFTFLOAT_ROUND_ODD +
+Can be defined to enable support for optional rounding mode +softfloat_round_odd. +
+
+
INLINE_LEVEL +
+Can be defined to an integer to determine the degree of inlining requested of +the compiler. +Larger numbers request that more inlining be done. +If this macro is not defined or is defined to a value less than 1 +(zero or negative), no inlining is requested. +The maximum effective value is no higher than 5. +Defining this macro to a value greater than 5 is the same as defining it +to 5. +
SOFTFLOAT_FAST_INT64 +
+Can be defined to indicate that the build target’s implementation of +64-bit arithmetic is efficient. +For newer 64-bit processors, this macro should usually be defined. +For very small microprocessors whose buses and registers are 8-bit +or 16-bit in size, this macro should usually not be defined. +Whether this macro should be defined for a 32-bit processor may +depend on the target machine and the applications that will use SoftFloat. +
SOFTFLOAT_FAST_DIV32TO16 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 32-bit unsigned integer by a 16-bit +unsigned integer. +Setting this macro may affect the performance of function f16_div. +
SOFTFLOAT_FAST_DIV64TO32 +
+Can be defined to indicate that the target’s division operator +in C (written as /) is reasonably efficient for +dividing a 64-bit unsigned integer by a 32-bit +unsigned integer. +Setting this macro may affect the performance of division, remainder, and +square root operations other than f16_div. +
+
+

+ +

+Following the usual custom for C, for most of these macros (all +except INLINE, THREAD_LOCAL, and +INLINE_LEVEL), the content of any definition is irrelevant; +what matters is a macro’s effect on #ifdef directives. +

+ +

+It is recommended that any definitions of macros LITTLEENDIAN, +INLINE, and THREAD_LOCAL be made in a build +target’s platform.h header file, because these macros are +expected to be determined inflexibly by the target machine and compiler. +The other five macros select options and control optimization, and thus might +be better located in the target’s Makefile (or its equivalent). +

+ + +

5.4. Adapting a Template Target Directory

+ +

+In the build directory, two template subdirectories +provide models for new target directories. +Two different templates exist because different functions are needed in the +SoftFloat library depending on whether macro SOFTFLOAT_FAST_INT64 +is defined. +If macro SOFTFLOAT_FAST_INT64 will be defined, +template-FAST_INT64 is the template to use; +otherwise, template-not-FAST_INT64 is the appropriate +template. +A new target directory can be created by copying the correct template directory +and editing the files inside. +To avoid confusion, it would be wise to refrain from editing the files within a +template directory directly. +

+ + +

5.5. Target-Specific Optimization of Primitive Functions

+ +

+Header file primitives.h (in directory +source/include) declares macros and functions for numerous +underlying arithmetic operations upon which many of SoftFloat’s +floating-point functions are ultimately built. +The SoftFloat sources include implementations of all of these functions/macros, +written as standard C code, so a complete and correct SoftFloat library can be +created using only the supplied code for all functions. +However, for many targets, SoftFloat’s performance can be improved by +substituting target-specific implementations of some of the functions/macros +declared in primitives.h. +

+ +

+For example, primitives.h declares a function called +softfloat_countLeadingZeros32 that takes an unsigned +32-bit integer as an argument and returns the number of the +integer’s most-significant bits that are zeros. +While the SoftFloat sources include an implementation of this function written +in standard C, many processors can perform this same function +directly in only one or two machine instructions. +An alternative, target-specific implementation that maps to those instructions +is likely to be more efficient than the generic C code from the SoftFloat +package. +

+ +

+A build target can replace the supplied version of any function or macro of +primitives.h by defining a macro with the same name in the +target’s platform.h header file. +For this purpose, it may be helpful for platform.h to +#include header file primitiveTypes.h, which defines +types used for arguments and results of functions declared in +primitives.h. +When a desired replacement implementation is a function, not a macro, it is +sufficient for platform.h to include the line +

+
+#define <function-name> <function-name>
+
+
+where <function-name> is the name of the +function. +This technically defines <function-name> +as a macro, but one that resolves to the same name, which may then be a +function. +(A preprocessor that conforms to the C Standard is required to limit recursive +macro expansion from being applied more than once.) +

+ +

+The supplied header file opts-GCC.h (in directory +source/include) provides an example of target-specific +optimization for the GCC compiler. +Each GCC target example in the build directory has +

+#include "opts-GCC.h" +
+in its platform.h header file. +Before opts-GCC.h is included, the following macros must be +defined (or not) to control which features are invoked: +
+
+
SOFTFLOAT_BUILTIN_CLZ
+
+If defined, SoftFloat’s internal +‘countLeadingZeros’ functions use intrinsics +__builtin_clz and __builtin_clzll. +
+
SOFTFLOAT_INTRINSIC_INT128
+
+If defined, SoftFloat makes use of GCC’s nonstandard 128-bit +integer type __int128. +
+
+
+On some machines, these improvements are observed to increase the speeds of +f64_mul and f128_mul by around 20 to 25%, although +other functions receive less dramatic boosts, or none at all. +Results can vary greatly across different platforms. +

+ + +

6. Testing SoftFloat

+ +

+SoftFloat can be tested using the testsoftfloat program by the +same author. +This program is part of the Berkeley TestFloat package available at the Web +page +http://www.jhauser.us/arithmetic/TestFloat.html. +The TestFloat package also has a program called timesoftfloat that +measures the speed of SoftFloat’s floating-point functions. +

+ + +

7. Providing SoftFloat as a Common Library for Applications

+ +

+Header file softfloat.h defines the SoftFloat interface as seen by +clients. +If the SoftFloat library will be made a common library for programs on a +system, the supplied softfloat.h has a couple of deficiencies for +this purpose: +

    +
  • +As supplied, softfloat.h depends on another header, +softfloat_types.h, that is not intended for public use but which +must also be visible to the programmer’s compiler. +
  • +More troubling, at the time softfloat.h is included in a C source +file, macros SOFTFLOAT_FAST_INT64 and THREAD_LOCAL +must be defined, or not defined, consistent with how these macro were defined +when the SoftFloat library was built. +
+In the situation that new programs may regularly #include header +file softfloat.h, it is recommended that a custom, self-contained +version of this header file be created that eliminates these issues. +

+ + +

8. Contact Information

+ +

+At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page +http://www.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/src/cpu/softfloat3e/doc/SoftFloat.html b/src/cpu/softfloat3e/doc/SoftFloat.html new file mode 100644 index 0000000000..b72b407f4f --- /dev/null +++ b/src/cpu/softfloat3e/doc/SoftFloat.html @@ -0,0 +1,1527 @@ + + + + +Berkeley SoftFloat Library Interface + + + + +

Berkeley SoftFloat Release 3e: Library Interface

+ +

+John R. Hauser
+2018 January 20
+

+ + +

Contents

+ +
+ +++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1. Introduction
2. Limitations
3. Acknowledgments and License
4. Types and Functions
4.1. Boolean and Integer Types
4.2. Floating-Point Types
4.3. Supported Floating-Point Functions
4.4. Non-canonical Representations in extFloat80_t
4.5. Conventions for Passing Arguments and Results
5. Reserved Names
6. Mode Variables
6.1. Rounding Mode
6.2. Underflow Detection
6.3. Rounding Precision for the 80-Bit Extended Format
7. Exceptions and Exception Flags
8. Function Details
8.1. Conversions from Integer to Floating-Point
8.2. Conversions from Floating-Point to Integer
8.3. Conversions Among Floating-Point Types
8.4. Basic Arithmetic Functions
8.5. Fused Multiply-Add Functions
8.6. Remainder Functions
8.7. Round-to-Integer Functions
8.8. Comparison Functions
8.9. Signaling NaN Test Functions
8.10. Raise-Exception Function
9. Changes from SoftFloat Release 2
9.1. Name Changes
9.2. Changes to Function Arguments
9.3. Added Capabilities
9.4. Better Compatibility with the C Language
9.5. New Organization as a Library
9.6. Optimization Gains (and Losses)
10. Future Directions
11. Contact Information
+
+ + +

1. Introduction

+ +

+Berkeley SoftFloat is a software implementation of binary floating-point that +conforms to the IEEE Standard for Floating-Point Arithmetic. +The current release supports five binary formats: 16-bit +half-precision, 32-bit single-precision, 64-bit +double-precision, 80-bit double-extended-precision, and +128-bit quadruple-precision. +The following functions are supported for each format: +

    +
  • +addition, subtraction, multiplication, division, and square root; +
  • +fused multiply-add as defined by the IEEE Standard, except for +80-bit double-extended-precision; +
  • +remainder as defined by the IEEE Standard; +
  • +round to integral value; +
  • +comparisons; +
  • +conversions to/from other supported formats; and +
  • +conversions to/from 32-bit and 64-bit integers, +signed and unsigned. +
+All operations required by the original 1985 version of the IEEE Floating-Point +Standard are implemented, except for conversions to and from decimal. +

+ +

+This document gives information about the types defined and the routines +implemented by SoftFloat. +It does not attempt to define or explain the IEEE Floating-Point Standard. +Information about the standard is available elsewhere. +

+ +

+The current version of SoftFloat is Release 3e. +This release modifies the behavior of the rarely used odd rounding mode +(round to odd, also known as jamming), and also adds some new +specialization and optimization examples for those compiling SoftFloat. +

+ +

+The previous Release 3d fixed bugs that were found in the square +root functions for the 64-bit, 80-bit, and +128-bit floating-point formats. +(Thanks to Alexei Sibidanov at the University of Victoria for reporting an +incorrect result.) +The bugs affected all prior Release-3 versions of SoftFloat +through 3c. +The flaw in the 64-bit floating-point square root function was of +very minor impact, causing a 1-ulp error (1 unit in +the last place) a few times out of a billion. +The bugs in the 80-bit and 128-bit square root +functions were more serious. +Although incorrect results again occurred only a few times out of a billion, +when they did occur a large portion of the less-significant bits could be +wrong. +

+ +

+Among earlier releases, 3b was notable for adding support for the +16-bit half-precision format. +For more about the evolution of SoftFloat releases, see +SoftFloat-history.html. +

+ +

+The functional interface of SoftFloat Release 3 and later differs +in many details from the releases that came before. +For specifics of these differences, see section 9 below, +Changes from SoftFloat Release 2. +

+ + +

2. Limitations

+ +

+SoftFloat assumes the computer has an addressable byte size of 8 or +16 bits. +(Nearly all computers in use today have 8-bit bytes.) +

+ +

+SoftFloat is written in C and is designed to work with other C code. +The C compiler used must conform at a minimum to the 1989 ANSI standard for the +C language (same as the 1990 ISO standard) and must in addition support basic +arithmetic on 64-bit integers. +Earlier releases of SoftFloat included implementations of 32-bit +single-precision and 64-bit double-precision floating-point that +did not require 64-bit integers, but this option is not supported +starting with Release 3. +Since 1999, ISO standards for C have mandated compiler support for +64-bit integers. +A compiler conforming to the 1999 C Standard or later is recommended but not +strictly required. +

+ +

+Most operations not required by the original 1985 version of the IEEE +Floating-Point Standard but added in the 2008 version are not yet supported in +SoftFloat Release 3e. +

+ + +

3. Acknowledgments and License

+ +

+The SoftFloat package was written by me, John R. Hauser. +Release 3 of SoftFloat was a completely new implementation +supplanting earlier releases. +The project to create Release 3 (now through 3e) was +done in the employ of the University of California, Berkeley, within the +Department of Electrical Engineering and Computer Sciences, first for the +Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. +The work was officially overseen by Prof. Krste Asanovic, with funding provided +by these sources: +

+ ++++ + + + + + + + + + +
Par Lab: +Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery +(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, +NVIDIA, Oracle, and Samsung. +
ASPIRE Lab: +DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from +ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, +Oracle, and Samsung. +
+
+

+ +

+The following applies to the whole of SoftFloat Release 3e as well +as to each source file individually. +

+ +

+Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. +All rights reserved. +

+ +

+Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +

    + +
  1. +

    +Redistributions of source code must retain the above copyright notice, this +list of conditions, and the following disclaimer. +

    + +
  2. +

    +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions, and the following disclaimer in the documentation and/or +other materials provided with the distribution. +

    + +
  3. +

    +Neither the name of the University nor the names of its contributors may be +used to endorse or promote products derived from this software without specific +prior written permission. +

    + +
+

+ +

+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS “AS IS”, +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. +IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +

+ + +

4. Types and Functions

+ +

+The types and functions of SoftFloat are declared in header file +softfloat.h. +

+ +

4.1. Boolean and Integer Types

+ +

+Header file softfloat.h depends on standard headers +<stdbool.h> and <stdint.h> to define type +bool and several integer types. +These standard headers have been part of the ISO C Standard Library since 1999. +With any recent compiler, they are likely to be supported, even if the compiler +does not claim complete conformance to the latest ISO C Standard. +For older or nonstandard compilers, a port of SoftFloat may have substitutes +for these headers. +Header softfloat.h depends only on the name bool from +<stdbool.h> and on these type names from +<stdint.h>: +

+
+uint16_t
+uint32_t
+uint64_t
+int32_t
+int64_t
+uint_fast8_t
+uint_fast32_t
+uint_fast64_t
+int_fast32_t
+int_fast64_t
+
+
+

+ + +

4.2. Floating-Point Types

+ +

+The softfloat.h header defines five floating-point types: +

+ + + + + + + + + + + + + + + + + + + + + +
float16_t16-bit half-precision binary format
float32_t32-bit single-precision binary format
float64_t64-bit double-precision binary format
extFloat80_t   80-bit double-extended-precision binary format (old Intel or +Motorola format)
float128_t128-bit quadruple-precision binary format
+
+The non-extended types are each exactly the size specified: +16 bits for float16_t, 32 bits for +float32_t, 64 bits for float64_t, and +128 bits for float128_t. +Aside from these size requirements, the definitions of all these types may +differ for different ports of SoftFloat to specific systems. +A given port of SoftFloat may or may not define some of the floating-point +types as aliases for the C standard types float, +double, and long double. +

+ +

+Header file softfloat.h also defines a structure, +struct extFloat80M, for the representation of +80-bit double-extended-precision floating-point values in memory. +This structure is the same size as type extFloat80_t and contains +at least these two fields (not necessarily in this order): +

+
+uint16_t signExp;
+uint64_t signif;
+
+
+Field signExp contains the sign and exponent of the floating-point +value, with the sign in the most significant bit (bit 15) and the +encoded exponent in the other 15 bits. +Field signif is the complete 64-bit significand of +the floating-point value. +(In the usual encoding for 80-bit extended floating-point, the +leading 1 bit of normalized numbers is not implicit but is stored +in the most significant bit of the significand.) +

+ +

4.3. Supported Floating-Point Functions

+ +

+SoftFloat implements these arithmetic operations for its floating-point types: +

    +
  • +conversions between any two floating-point formats; +
  • +for each floating-point format, conversions to and from signed and unsigned +32-bit and 64-bit integers; +
  • +for each format, the usual addition, subtraction, multiplication, division, and +square root operations; +
  • +for each format except extFloat80_t, the fused multiply-add +operation defined by the IEEE Standard; +
  • +for each format, the floating-point remainder operation defined by the IEEE +Standard; +
  • +for each format, a “round to integer” operation that rounds to the +nearest integer value in the same format; and +
  • +comparisons between two values in the same floating-point format. +
+

+ +

+The following operations required by the 2008 IEEE Floating-Point Standard are +not supported in SoftFloat Release 3e: +

    +
  • +nextUp, nextDown, minNum, maxNum, minNumMag, +maxNumMag, scaleB, and logB; +
  • +conversions between floating-point formats and decimal or hexadecimal character +sequences; +
  • +all “quiet-computation” operations (copy, negate, +abs, and copySign, which all involve only simple copying and/or +manipulation of the floating-point sign bit); and +
  • +all “non-computational” operations other than isSignaling +(which is supported). +
+

+ +

4.4. Non-canonical Representations in extFloat80_t

+ +

+Because the 80-bit double-extended-precision format, +extFloat80_t, stores an explicit leading significand bit, many +finite floating-point numbers are encodable in this type in multiple equivalent +forms. +Of these multiple encodings, there is always a unique one with the least +encoded exponent value, and this encoding is considered the canonical +representation of the floating-point number. +Any other equivalent representations (having a higher encoded exponent value) +are non-canonical. +For a value in the subnormal range (including zero), the canonical +representation always has an encoded exponent of zero and a leading significand +bit of 0. +For finite values outside the subnormal range, the canonical representation +always has an encoded exponent that is nonzero and a leading significand bit +of 1. +

+ +

+For an infinity or NaN, the leading significand bit is similarly expected to +be 1. +An infinity or NaN with a leading significand bit of 0 is again +considered non-canonical. +Hence, altogether, to be canonical, a value of type extFloat80_t +must have a leading significand bit of 1, unless the value is +subnormal or zero, in which case the leading significand bit and the encoded +exponent must both be zero. +

+ +

+SoftFloat’s functions are not guaranteed to operate as expected when +inputs of type extFloat80_t are non-canonical. +Assuming all of a function’s extFloat80_t inputs (if any) +are canonical, function outputs of type extFloat80_t will always +be canonical. +

+ +

4.5. Conventions for Passing Arguments and Results

+ +

+Values that are at most 64 bits in size (i.e., not the +80-bit or 128-bit floating-point formats) are in all +cases passed as function arguments by value. +Likewise, when an output of a function is no more than 64 bits, it +is always returned directly as the function result. +Thus, for example, the SoftFloat function for adding two 64-bit +floating-point values has this simple signature: +

+float64_t f64_add( float64_t, float64_t ); +
+

+ +

+The story is more complex when function inputs and outputs are +80-bit and 128-bit floating-point. +For these types, SoftFloat always provides a function that passes these larger +values into or out of the function indirectly, via pointers. +For example, for adding two 128-bit floating-point values, +SoftFloat supplies this function: +

+void f128M_add( const float128_t *, const float128_t *, float128_t * ); +
+The first two arguments point to the values to be added, and the last argument +points to the location where the sum will be stored. +The M in the name f128M_add is mnemonic for the fact +that the 128-bit inputs and outputs are “in memory”, +pointed to by pointer arguments. +

+ +

+All ports of SoftFloat implement these pass-by-pointer functions for +types extFloat80_t and float128_t. +At the same time, SoftFloat ports may also implement alternate versions of +these same functions that pass extFloat80_t and +float128_t by value, like the smaller formats. +Thus, besides the function with name f128M_add shown above, a +SoftFloat port may also supply an equivalent function with this signature: +

+float128_t f128_add( float128_t, float128_t ); +
+

+ +

+As a general rule, on computers where the machine word size is +32 bits or smaller, only the pass-by-pointer versions of functions +(e.g., f128M_add) are provided for types extFloat80_t +and float128_t, because passing such large types directly can have +significant extra cost. +On computers where the word size is 64 bits or larger, both +function versions (f128M_add and f128_add) are +provided, because the cost of passing by value is then more reasonable. +Applications that must be portable accross both classes of computers must use +the pointer-based functions, as these are always implemented. +However, if it is known that SoftFloat includes the by-value functions for all +platforms of interest, programmers can use whichever version they prefer. +

+ + +

5. Reserved Names

+ +

+In addition to the variables and functions documented here, SoftFloat defines +some symbol names for its own private use. +These private names always begin with the prefix +‘softfloat_’. +When a program includes header softfloat.h or links with the +SoftFloat library, all names with prefix ‘softfloat_’ +are reserved for possible use by SoftFloat. +Applications that use SoftFloat should not define their own names with this +prefix, and should reference only such names as are documented. +

+ + +

6. Mode Variables

+ +

+The following global variables control rounding mode, underflow detection, and +the 80-bit extended format’s rounding precision: +

+softfloat_roundingMode
+softfloat_detectTininess
+extF80_roundingPrecision +
+These mode variables are covered in the next several subsections. +For some SoftFloat ports, these variables may be per-thread (declared +thread_local), meaning that different execution threads have their +own separate copies of the variables. +

+ +

6.1. Rounding Mode

+ +

+All five rounding modes defined by the 2008 IEEE Floating-Point Standard are +implemented for all operations that require rounding. +Some ports of SoftFloat may also implement the round-to-odd mode. +

+ +

+The rounding mode is selected by the global variable +

+uint_fast8_t softfloat_roundingMode; +
+This variable may be set to one of the values +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
softfloat_round_near_evenround to nearest, with ties to even
softfloat_round_near_maxMag  round to nearest, with ties to maximum magnitude (away from zero)
softfloat_round_minMaground to minimum magnitude (toward zero)
softfloat_round_minround to minimum (down)
softfloat_round_maxround to maximum (up)
softfloat_round_oddround to odd (jamming), if supported by the SoftFloat port
+
+Variable softfloat_roundingMode is initialized to +softfloat_round_near_even. +

+ +

+When softfloat_round_odd is the rounding mode for a function that +rounds to an integer value (either conversion to an integer format or a +‘roundToInt’ function), if the input is not already an +integer, the rounded result is the closest odd integer. +For other operations, this rounding mode acts as though the floating-point +result is first rounded to minimum magnitude, the same as +softfloat_round_minMag, and then, if the result is inexact, the +least-significant bit of the result is set to 1. +Rounding to odd is also known as jamming. +

+ +

6.2. Underflow Detection

+ +

+In the terminology of the IEEE Standard, SoftFloat can detect tininess for +underflow either before or after rounding. +The choice is made by the global variable +

+uint_fast8_t softfloat_detectTininess; +
+which can be set to either +
+softfloat_tininess_beforeRounding
+softfloat_tininess_afterRounding +
+Detecting tininess after rounding is usually better because it results in fewer +spurious underflow signals. +The other option is provided for compatibility with some systems. +Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat +always detects loss of accuracy for underflow as an inexact result. +

+ +

6.3. Rounding Precision for the 80-Bit Extended Format

+ +

+For extFloat80_t only, the rounding precision of the basic +arithmetic operations is controlled by the global variable +

+uint_fast8_t extF80_roundingPrecision; +
+The operations affected are: +
+extF80_add
+extF80_sub
+extF80_mul
+extF80_div
+extF80_sqrt +
+When extF80_roundingPrecision is set to its default value of 80, +these operations are rounded to the full precision of the 80-bit +double-extended-precision format, like occurs for other formats. +Setting extF80_roundingPrecision to 32 or to 64 causes the +operations listed to be rounded to 32-bit precision (equivalent to +float32_t) or to 64-bit precision (equivalent to +float64_t), respectively. +When rounding to reduced precision, additional bits in the result significand +beyond the rounding point are set to zero. +The consequences of setting extF80_roundingPrecision to a value +other than 32, 64, or 80 is not specified. +Operations other than the ones listed above are not affected by +extF80_roundingPrecision. +

+ + +

7. Exceptions and Exception Flags

+ +

+All five exception flags required by the IEEE Floating-Point Standard are +implemented. +Each flag is stored as a separate bit in the global variable +

+uint_fast8_t softfloat_exceptionFlags; +
+The positions of the exception flag bits within this variable are determined by +the bit masks +
+softfloat_flag_inexact
+softfloat_flag_underflow
+softfloat_flag_overflow
+softfloat_flag_infinite
+softfloat_flag_invalid +
+Variable softfloat_exceptionFlags is initialized to all zeros, +meaning no exceptions. +

+ +

+For some SoftFloat ports, softfloat_exceptionFlags may be +per-thread (declared thread_local), meaning that different +execution threads have their own separate instances of it. +

+ +

+An individual exception flag can be cleared with the statement +

+softfloat_exceptionFlags &= ~softfloat_flag_<exception>; +
+where <exception> is the appropriate name. +To raise a floating-point exception, function softfloat_raiseFlags +should normally be used. +

+ +

+When SoftFloat detects an exception other than inexact, it calls +softfloat_raiseFlags. +The default version of this function simply raises the corresponding exception +flags. +Particular ports of SoftFloat may support alternate behavior, such as exception +traps, by modifying the default softfloat_raiseFlags. +A program may also supply its own softfloat_raiseFlags function to +override the one from the SoftFloat library. +

+ +

+Because inexact results occur frequently under most circumstances (and thus are +hardly exceptional), SoftFloat does not ordinarily call +softfloat_raiseFlags for inexact exceptions. +It does always raise the inexact exception flag as required. +

+ + +

8. Function Details

+ +

+In this section, <float> appears in function names as +a substitute for one of these abbreviations: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
f16indicates float16_t, passed by value
f32indicates float32_t, passed by value
f64indicates float64_t, passed by value
extF80M   indicates extFloat80_t, passed indirectly via pointers
extF80indicates extFloat80_t, passed by value
f128Mindicates float128_t, passed indirectly via pointers
f128indicates float128_t, passed by value
+
+The circumstances under which values of floating-point types +extFloat80_t and float128_t may be passed either by +value or indirectly via pointers was discussed earlier in +section 4.5, Conventions for Passing Arguments and Results. +

+ +

8.1. Conversions from Integer to Floating-Point

+ +

+All conversions from a 32-bit or 64-bit integer, +signed or unsigned, to a floating-point format are supported. +Functions performing these conversions have these names: +

+ui32_to_<float>
+ui64_to_<float>
+i32_to_<float>
+i64_to_<float> +
+Conversions from 32-bit integers to 64-bit +double-precision and larger formats are always exact, and likewise conversions +from 64-bit integers to 80-bit +double-extended-precision and 128-bit quadruple-precision are also +always exact. +

+ +

+Each conversion function takes one input of the appropriate type and generates +one output. +The following illustrates the signatures of these functions in cases when the +floating-point result is passed either by value or via pointers: +

+
+float64_t i32_to_f64( int32_t a );
+
+
+void i32_to_f128M( int32_t a, float128_t *destPtr );
+
+
+

+ +

8.2. Conversions from Floating-Point to Integer

+ +

+Conversions from a floating-point format to a 32-bit or +64-bit integer, signed or unsigned, are supported with these +functions: +

+<float>_to_ui32
+<float>_to_ui64
+<float>_to_i32
+<float>_to_i64 +
+The functions have signatures as follows, depending on whether the +floating-point input is passed by value or via pointers: +
+
+int_fast32_t f64_to_i32( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+int_fast32_t
+ f128M_to_i32( const float128_t *aPtr, uint_fast8_t roundingMode, bool exact );
+
+
+

+ +

+The roundingMode argument specifies the rounding mode for +the conversion. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

+A conversion from floating-point to integer format raises the invalid +exception if the source value cannot be rounded to a representable integer of +the desired size (32 or 64 bits). +In such circumstances, the integer result returned is determined by the +particular port of SoftFloat, although typically this value will be either the +maximum or minimum value of the integer format. +The functions that convert to integer types never raise the floating-point +overflow exception. +

+ +

+Because languages such as C require that conversions to integers +be rounded toward zero, the following functions are provided for improved speed +and convenience: +

+<float>_to_ui32_r_minMag
+<float>_to_ui64_r_minMag
+<float>_to_i32_r_minMag
+<float>_to_i64_r_minMag +
+These functions round only toward zero (to minimum magnitude). +The signatures for these functions are the same as above without the redundant +roundingMode argument: +
+
+int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact );
+
+
+int_fast32_t f128M_to_i32_r_minMag( const float128_t *aPtr, bool exact );
+
+
+

+ +

8.3. Conversions Among Floating-Point Types

+ +

+Conversions between floating-point formats are done by functions with these +names: +

+<float>_to_<float> +
+All combinations of source and result type are supported where the source and +result are different formats. +There are four different styles of signature for these functions, depending on +whether the input and the output floating-point values are passed by value or +via pointers: +
+
+float32_t f64_to_f32( float64_t a );
+
+
+float32_t f128M_to_f32( const float128_t *aPtr );
+
+
+void f32_to_f128M( float32_t a, float128_t *destPtr );
+
+
+void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *destPtr );
+
+
+

+ +

+Conversions from a smaller to a larger floating-point format are always exact +and so require no rounding. +

+ +

8.4. Basic Arithmetic Functions

+ +

+The following basic arithmetic functions are provided: +

+<float>_add
+<float>_sub
+<float>_mul
+<float>_div
+<float>_sqrt +
+Each floating-point operation takes two operands, except for sqrt +(square root) which takes only one. +The operands and result are all of the same floating-point format. +Signatures for these functions take the following forms: +
+
+float64_t f64_add( float64_t a, float64_t b );
+
+
+void
+ f128M_add(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+float64_t f64_sqrt( float64_t a );
+
+
+void f128M_sqrt( const float128_t *aPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to the input +operands, and the last argument, destPtr, points to the +location where the result is stored. +

+ +

+Rounding of the 80-bit double-extended-precision +(extFloat80_t) functions is affected by variable +extF80_roundingPrecision, as explained earlier in +section 6.3, +Rounding Precision for the 80-Bit Extended Format. +

+ +

8.5. Fused Multiply-Add Functions

+ +

+The 2008 version of the IEEE Floating-Point Standard defines a fused +multiply-add operation that does a combined multiplication and addition +with only a single rounding. +SoftFloat implements fused multiply-add with functions +

+<float>_mulAdd +
+Unlike other operations, fused multiple-add is not supported for the +80-bit double-extended-precision format, +extFloat80_t. +

+ +

+Depending on whether floating-point values are passed by value or via pointers, +the fused multiply-add functions have signatures of these forms: +

+
+float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c );
+
+
+void
+ f128M_mulAdd(
+     const float128_t *aPtr,
+     const float128_t *bPtr,
+     const float128_t *cPtr,
+     float128_t *destPtr
+ );
+
+
+The functions compute +(a × b) + + c +with a single rounding. +When floating-point values are passed indirectly through pointers, arguments +aPtr, bPtr, and +cPtr point to operands a, +b, and c respectively, and +destPtr points to the location where the result is stored. +

+ +

+If one of the multiplication operands a and +b is infinite and the other is zero, these functions raise +the invalid exception even if operand c is a quiet NaN. +

+ +

8.6. Remainder Functions

+ +

+For each format, SoftFloat implements the remainder operation defined by the +IEEE Floating-Point Standard. +The remainder functions have names +

+<float>_rem +
+Each remainder operation takes two floating-point operands of the same format +and returns a result in the same format. +Depending on whether floating-point values are passed by value or via pointers, +the remainder functions have signatures of these forms: +
+
+float64_t f64_rem( float64_t a, float64_t b );
+
+
+void
+ f128M_rem(
+     const float128_t *aPtr, const float128_t *bPtr, float128_t *destPtr );
+
+
+When floating-point values are passed indirectly through pointers, arguments +aPtr and bPtr point to operands +a and b respectively, and +destPtr points to the location where the result is stored. +

+ +

+The IEEE Standard remainder operation computes the value +a + − n × b, +where n is the integer closest to +a ÷ b. +If a ÷ b is exactly +halfway between two integers, n is the even integer closest to +a ÷ b. +The IEEE Standard’s remainder operation is always exact and so requires +no rounding. +

+ +

+Depending on the relative magnitudes of the operands, the remainder +functions can take considerably longer to execute than the other SoftFloat +functions. +This is an inherent characteristic of the remainder operation itself and is not +a flaw in the SoftFloat implementation. +

+ +

8.7. Round-to-Integer Functions

+ +

+For each format, SoftFloat implements the round-to-integer operation specified +by the IEEE Floating-Point Standard. +These functions are named +

+<float>_roundToInt +
+Each round-to-integer operation takes a single floating-point operand. +This operand is rounded to an integer according to a specified rounding mode, +and the resulting integer value is returned in the same floating-point format. +(Note that the result is not an integer type.) +

+ +

+The signatures of the round-to-integer functions are similar to those for +conversions to an integer type: +

+
+float64_t f64_roundToInt( float64_t a, uint_fast8_t roundingMode, bool exact );
+
+
+void
+ f128M_roundToInt(
+     const float128_t *aPtr,
+     uint_fast8_t roundingMode,
+     bool exact,
+     float128_t *destPtr
+ );
+
+
+When floating-point values are passed indirectly through pointers, +aPtr points to the input operand and +destPtr points to the location where the result is stored. +

+ +

+The roundingMode argument specifies the rounding mode to +apply. +The variable that usually indicates rounding mode, +softfloat_roundingMode, is ignored. +Argument exact determines whether the inexact +exception flag is raised if the conversion is not exact. +If exact is true, the inexact flag may +be raised; +otherwise, it will not be, even if the conversion is inexact. +

+ +

8.8. Comparison Functions

+ +

+For each format, the following floating-point comparison functions are +provided: +

+<float>_eq
+<float>_le
+<float>_lt +
+Each comparison takes two operands of the same type and returns a Boolean. +The abbreviation eq stands for “equal” (=); +le stands for “less than or equal” (≤); +and lt stands for “less than” (<). +Depending on whether the floating-point operands are passed by value or via +pointers, the comparison functions have signatures of these forms: +
+
+bool f64_eq( float64_t a, float64_t b );
+
+
+bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr );
+
+
+

+ +

+The usual greater-than (>), greater-than-or-equal (≥), and not-equal +(≠) comparisons are easily obtained from the functions provided. +The not-equal function is just the logical complement of the equal function. +The greater-than-or-equal function is identical to the less-than-or-equal +function with the arguments in reverse order, and likewise the greater-than +function is identical to the less-than function with the arguments reversed. +

+ +

+The IEEE Floating-Point Standard specifies that the less-than-or-equal and +less-than comparisons by default raise the invalid exception if either +operand is any kind of NaN. +Equality comparisons, on the other hand, are defined by default to raise the +invalid exception only for signaling NaNs, not quiet NaNs. +For completeness, SoftFloat provides these complementary functions: +

+<float>_eq_signaling
+<float>_le_quiet
+<float>_lt_quiet +
+The signaling equality comparisons are identical to the default +equality comparisons except that the invalid exception is raised for any +NaN input, not just for signaling NaNs. +Similarly, the quiet comparison functions are identical to their +default counterparts except that the invalid exception is not raised for +quiet NaNs. +

+ +

8.9. Signaling NaN Test Functions

+ +

+Functions for testing whether a floating-point value is a signaling NaN are +provided with these names: +

+<float>_isSignalingNaN +
+The functions take one floating-point operand and return a Boolean indicating +whether the operand is a signaling NaN. +Accordingly, the functions have the forms +
+
+bool f64_isSignalingNaN( float64_t a );
+
+
+bool f128M_isSignalingNaN( const float128_t *aPtr );
+
+
+

+ +

8.10. Raise-Exception Function

+ +

+SoftFloat provides a single function for raising floating-point exceptions: +

+
+void softfloat_raiseFlags( uint_fast8_t exceptions );
+
+
+The exceptions argument is a mask indicating the set of +exceptions to raise. +(See earlier section 7, Exceptions and Exception Flags.) +In addition to setting the specified exception flags in variable +softfloat_exceptionFlags, the softfloat_raiseFlags +function may cause a trap or abort appropriate for the current system. +

+ + +

9. Changes from SoftFloat Release 2

+ +

+Apart from a change in the legal use license, Release 3 of +SoftFloat introduced numerous technical differences compared to earlier +releases. +

+ +

9.1. Name Changes

+ +

+The most obvious and pervasive difference compared to Release 2 +is that the names of most functions and variables have changed, even when the +behavior has not. +First, the floating-point types, the mode variables, the exception flags +variable, the function to raise exceptions, and various associated constants +have been renamed as follows: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
old name, Release 2:new name, Release 3:
float32float32_t
float64float64_t
floatx80extFloat80_t
float128float128_t
float_rounding_modesoftfloat_roundingMode
float_round_nearest_evensoftfloat_round_near_even
float_round_to_zerosoftfloat_round_minMag
float_round_downsoftfloat_round_min
float_round_upsoftfloat_round_max
float_detect_tininesssoftfloat_detectTininess
float_tininess_before_rounding    softfloat_tininess_beforeRounding
float_tininess_after_roundingsoftfloat_tininess_afterRounding
floatx80_rounding_precisionextF80_roundingPrecision
float_exception_flagssoftfloat_exceptionFlags
float_flag_inexactsoftfloat_flag_inexact
float_flag_underflowsoftfloat_flag_underflow
float_flag_overflowsoftfloat_flag_overflow
float_flag_divbyzerosoftfloat_flag_infinite
float_flag_invalidsoftfloat_flag_invalid
float_raisesoftfloat_raiseFlags
+
+

+ +

+Furthermore, Release 3 adopted the following new abbreviations for +function names: +

+ + + + + + + + + + + +
used in names in Release 2:    used in names in Release 3:
int32 i32
int64 i64
float32 f32
float64 f64
floatx80 extF80
float128 f128
+
+Thus, for example, the function to add two 32-bit floating-point +numbers, previously called float32_add in Release 2, +is now f32_add. +Lastly, there have been a few other changes to function names: +
+ + + + + + + + + + + + + + + + + + + + + +
used in names in Release 2:   used in names in Release 3:   relevant functions:
_round_to_zero_r_minMagconversions from floating-point to integer (section 8.2)
round_to_introundToIntround-to-integer functions (section 8.7)
is_signaling_nan    isSignalingNaNsignaling NaN test functions (section 8.9)
+
+

+ +

9.2. Changes to Function Arguments

+ +

+Besides simple name changes, some operations were given a different interface +in Release 3 than they had in Release 2: +

    + +
  • +

    +Since Release 3, integer arguments and results of functions have +standard types from header <stdint.h>, such as +uint32_t, whereas previously their types could be defined +differently for each port of SoftFloat, usually using traditional C types such +as unsigned int. +Likewise, functions in Release 3 and later pass Booleans as +standard type bool from <stdbool.h>, whereas +previously these were again passed as a port-specific type (usually +int). +

    + +
  • +

    +As explained earlier in section 4.5, Conventions for Passing +Arguments and Results, SoftFloat functions in Release 3 and +later may pass 80-bit and 128-bit floating-point +values through pointers, meaning that functions take pointer arguments and then +read or write floating-point values at the locations indicated by the pointers. +In Release 2, floating-point arguments and results were always +passed by value, regardless of their size. +

    + +
  • +

    +Functions that round to an integer have additional +roundingMode and exact arguments that +they did not have in Release 2. +Refer to sections 8.2 and 8.7 for descriptions of these functions +since Release 3. +For Release 2, the rounding mode, when needed, was taken from the +same global variable that affects the basic arithmetic operations (now called +softfloat_roundingMode but previously known as +float_rounding_mode). +Also, for Release 2, if the original floating-point input was not +an exact integer value, and if the invalid exception was not raised by +the function, the inexact exception was always raised. +Release 2 had no option to suppress raising inexact in this +case. +Applications using SoftFloat Release 3 or later can get the same +effect as Release 2 by passing variable +softfloat_roundingMode for argument +roundingMode and true for argument +exact. +

    + +
+

+ +

9.3. Added Capabilities

+ +

+With Release 3, some new features have been added that were not +present in Release 2: +

    + +
  • +

    +A port of SoftFloat can now define any of the floating-point types +float32_t, float64_t, extFloat80_t, and +float128_t as aliases for C’s standard floating-point types +float, double, and long +double, using either #define or typedef. +This potential convenience was not supported under Release 2. +

    + +

    +(Note, however, that there may be a performance cost to defining +SoftFloat’s floating-point types this way, depending on the platform and +the applications using SoftFloat. +Ports of SoftFloat may choose to forgo the convenience in favor of better +speed.) +

    + +

    +

  • +As of Release 3b, 16-bit half-precision, +float16_t, is supported. +

    + +

    +

  • +Functions have been added for converting between the floating-point types and +unsigned integers. +Release 2 supported only signed integers, not unsigned. +

    + +

    +

  • +Fused multiply-add functions have been added for all floating-point formats +except 80-bit double-extended-precision, +extFloat80_t. +

    + +

    +

  • +New rounding modes are supported: +softfloat_round_near_maxMag (round to nearest, with ties to +maximum magnitude, away from zero), and, as of Release 3c, +optional softfloat_round_odd (round to odd, also known as +jamming). +

    + +
+

+ +

9.4. Better Compatibility with the C Language

+ +

+Release 3 of SoftFloat was written to conform better to the ISO C +Standard’s rules for portability. +For example, older releases of SoftFloat employed type conversions in ways +that, while commonly practiced, are not fully defined by the C Standard. +Such problematic type conversions have generally been replaced by the use of +unions, the behavior around which is more strictly regulated these days. +

+ +

9.5. New Organization as a Library

+ +

+Starting with Release 3, SoftFloat now builds as a library. +Previously, SoftFloat compiled into a single, monolithic object file containing +all the SoftFloat functions, with the consequence that a program linking with +SoftFloat would get every SoftFloat function in its binary file even if only a +few functions were actually used. +With SoftFloat in the form of a library, a program that is linked by a standard +linker will include only those functions of SoftFloat that it needs and no +others. +

+ +

9.6. Optimization Gains (and Losses)

+ +

+Individual SoftFloat functions have been variously improved in +Release 3 compared to earlier releases. +In particular, better, faster algorithms have been deployed for the operations +of division, square root, and remainder. +For functions operating on the larger 80-bit and +128-bit formats, extFloat80_t and +float128_t, code size has also generally been reduced. +

+ +

+However, because Release 2 compiled all of SoftFloat together as a +single object file, compilers could make optimizations across function calls +when one SoftFloat function calls another. +Now that the functions of SoftFloat are compiled separately and only afterward +linked together into a program, there is not usually the same opportunity to +optimize across function calls. +Some loss of speed has been observed due to this change. +

+ + +

10. Future Directions

+ +

+The following improvements are anticipated for future releases of SoftFloat: +

    +
  • +more functions from the 2008 version of the IEEE Floating-Point Standard; +
  • +consistent, defined behavior for non-canonical representations of extended +format extFloat80_t (discussed in section 4.4, +Non-canonical Representations in extFloat80_t). + +
+

+ + +

11. Contact Information

+ +

+At the time of this writing, the most up-to-date information about SoftFloat +and the latest release can be found at the Web page +http://www.jhauser.us/arithmetic/SoftFloat.html. +

+ + + + diff --git a/src/cpu/softfloat3e/extF80_addsub.cc b/src/cpu/softfloat3e/extF80_addsub.cc new file mode 100644 index 0000000000..a60d2c6be1 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_addsub.cc @@ -0,0 +1,106 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extern extFloat80_t softfloat_addMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *); +extern extFloat80_t softfloat_subMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *); + +extFloat80_t extF80_add(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + a.signExp = defaultNaNExtF80UI64; + a.signif = defaultNaNExtF80UI0; + return a; + } + + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + + if (signA == signB) { + return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} + +extFloat80_t extF80_sub(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + a.signExp = defaultNaNExtF80UI64; + a.signif = defaultNaNExtF80UI0; + return a; + } + + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + + if (signA == signB) { + return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} diff --git a/src/cpu/softfloat3e/extF80_class.cc b/src/cpu/softfloat3e/extF80_class.cc new file mode 100644 index 0000000000..155dc51a2a --- /dev/null +++ b/src/cpu/softfloat3e/extF80_class.cc @@ -0,0 +1,71 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t extF80_class(extFloat80_t a) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + + if (! expA) { + if (! sigA) return softfloat_zero; + return softfloat_denormal; /* denormal or pseudo-denormal */ + } + + /* valid numbers have the MS bit set */ + if (!(sigA & UINT64_C(0x8000000000000000))) + return softfloat_SNaN; /* report unsupported as SNaNs */ + + if (expA == 0x7FFF) { + if ((sigA<<1) == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & UINT64_C(0x4000000000000000)) ? softfloat_QNaN : softfloat_SNaN; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/extF80_compare.cc b/src/cpu/softfloat3e/extF80_compare.cc new file mode 100644 index 0000000000..f8a360a411 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_compare.cc @@ -0,0 +1,147 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include <86box/86box.h> +#include "../cpu.h" + +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two extended precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int extF80_compare(extFloat80_t a, extFloat80_t b, int quiet, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + softfloat_class_t aClass = extF80_class(a); + softfloat_class_t bClass = extF80_class(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (fpu_type < FPU_287XL) { + if ((aClass == softfloat_positive_inf) && (bClass == softfloat_negative_inf)) + { + return softfloat_relation_equal; + } + + if ((aClass == softfloat_negative_inf) && (bClass == softfloat_positive_inf)) + { + return softfloat_relation_equal; + } + } + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) + { + /* unsupported reported as SNaN */ + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (aClass == softfloat_denormal || bClass == softfloat_denormal) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (aClass == softfloat_zero) { + if (bClass == softfloat_zero) return softfloat_relation_equal; + return signB ? softfloat_relation_greater : softfloat_relation_less; + } + + if (bClass == softfloat_zero || signA != signB) { + return signA ? softfloat_relation_less : softfloat_relation_greater; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (aClass == softfloat_denormal) { + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp + 1; + sigA = normExpSig.sig; + } + if (bClass == softfloat_denormal) { + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp + 1; + sigB = normExpSig.sig; + } + + if (expA == expB && sigA == sigB) + return softfloat_relation_equal; + + int less_than = + signA ? ((expB < expA) || ((expB == expA) && (sigB < sigA))) + : ((expA < expB) || ((expA == expB) && (sigA < sigB))); + + if (less_than) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/extF80_div.cc b/src/cpu/softfloat3e/extF80_div.cc new file mode 100644 index 0000000000..e4b1fbb24b --- /dev/null +++ b/src/cpu/softfloat3e/extF80_div.cc @@ -0,0 +1,188 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_div(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + bool signZ; + struct exp32_sig64 normExpSig; + int32_t expZ; + struct uint128 rem; + uint32_t recip32; + uint64_t sigZ; + int ix; + uint64_t q64; + uint32_t q; + struct uint128 term; + uint64_t sigZExtra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) + goto invalid; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + goto invalid; + } + if (! expB && sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000)); + } + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + if (! expA && sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigB & UINT64_C(0x8000000000000000))) { + if (! sigB) { + if (! sigA) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000)); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) return packToExtF80(signZ, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFF; + if (sigA < sigB) { + --expZ; + rem = softfloat_shortShiftLeft128(0, sigA, 32); + } else { + rem = softfloat_shortShiftLeft128(0, sigA, 31); + } + recip32 = softfloat_approxRecip32_1(sigB>>32); + sigZ = 0; + ix = 2; + for (;;) { + q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if (ix < 0) break; + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, sigB>>32, sigB<<32); + } + sigZ = (sigZ<<29) + q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (((q + 1) & 0x3FFFFF) < 2) { + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + term = softfloat_shortShiftLeft128(0, sigB, 32); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, term.v64, term.v0); + } else if (softfloat_le128(term.v64, term.v0, rem.v64, rem.v0)) { + ++q; + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + } + if (rem.v64 | rem.v0) q |= 1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZ = (sigZ<<6) + (q>>23); + sigZExtra = (uint64_t) ((uint64_t) q<<41); + return + softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); +} diff --git a/src/cpu/softfloat3e/extF80_extract.cc b/src/cpu/softfloat3e/extF80_extract.cc new file mode 100644 index 0000000000..692190a47b --- /dev/null +++ b/src/cpu/softfloat3e/extF80_extract.cc @@ -0,0 +1,97 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Separate the source extended double-precision floating point value `a' +| into its exponent and significand, store the significant back to the +| 'a' and return the exponent. The operation performed is a superset of +| the IEC/IEEE recommended logb(x) function. +*----------------------------------------------------------------------------*/ + +extFloat80_t extF80_extract(extFloat80_t *a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(*a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + *a = packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + return *a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a->signExp; + uiA0 = a->signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA<<1) { + *a = softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); + return *a; + } + return packToExtF80(0, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + softfloat_raiseFlags(status, softfloat_flag_divbyzero); + *a = packToExtF80(signA, 0, 0); + return packToExtF80(1, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + + *a = packToExtF80(signA, 0x3FFF, sigA); + return i32_to_extF80(expA - 0x3FFF); +} diff --git a/src/cpu/softfloat3e/extF80_mul.cc b/src/cpu/softfloat3e/extF80_mul.cc new file mode 100644 index 0000000000..d38e97f026 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_mul.cc @@ -0,0 +1,153 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_mul(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + bool signZ; + uint64_t magBits; + struct exp32_sig64 normExpSig; + int32_t expZ; + struct uint128 sig128Z; + uint16_t uiZ64; + uint64_t uiZ0; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) { + goto propagateNaN; + } + magBits = expB | sigB; + goto infArg; + } + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + magBits = expA | sigA; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) { + if (! expB && sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigB & UINT64_C(0x8000000000000000))) { + if (! sigB) return packToExtF80(signZ, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sig128Z = softfloat_mul64To128(sigA, sigB); + if (sig128Z.v64 < UINT64_C(0x8000000000000000)) { + --expZ; + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0); + } + return + softfloat_roundPackToExtF80(signZ, expZ, sig128Z.v64, sig128Z.v0, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ64 = defaultNaNExtF80UI64; + uiZ0 = defaultNaNExtF80UI0; + } else { + if ((! expA && sigA) || (! expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + uiZ64 = packToExtF80UI64(signZ, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/extF80_rem.cc b/src/cpu/softfloat3e/extF80_rem.cc new file mode 100644 index 0000000000..39d233a7e4 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_rem.cc @@ -0,0 +1,199 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + int32_t expB; + uint64_t sigB; + struct exp32_sig64 normExpSig; + int32_t expDiff; + struct uint128 rem, shiftedSigB; + uint32_t q, recip32; + uint64_t q64; + struct uint128 term, altRem, meanRem; + bool signRem; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) + goto invalid; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) { + goto propagateNaN; + } + goto invalid; + } + if (expB == 0x7FFF) { + if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN; + /*-------------------------------------------------------------------- + | Argument b is an infinity. Doubling `expB' is an easy way to ensure + | that `expDiff' later is less than -1, which will result in returning + | a canonicalized version of argument a. + *--------------------------------------------------------------------*/ + expB += expB; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + expB = 1; + if (sigB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigB & UINT64_C(0x8000000000000000))) { + if (! sigB) goto invalid; + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB += normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) { + expA = 0; + goto copyA; + } + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (expDiff < -1) goto copyA; + rem = softfloat_shortShiftLeft128(0, sigA, 32); + shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 32); + if (expDiff < 1) { + if (expDiff) { + --expB; + shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 33); + q = 0; + } else { + q = (sigB <= sigA); + if (q) { + rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + } + } + } else { + recip32 = softfloat_approxRecip32_1(sigB>>32); + expDiff -= 30; + for (;;) { + q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32; + if (expDiff < 0) break; + q = (q64 + 0x80000000)>>32; + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + rem = softfloat_add128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + } + expDiff -= 29; + } + /*-------------------------------------------------------------------- + | (`expDiff' cannot be less than -29 here.) + *--------------------------------------------------------------------*/ + q = (uint32_t) (q64>>32)>>(~expDiff & 31); + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, expDiff + 30); + term = softfloat_mul64ByShifted32To128(sigB, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + altRem = softfloat_add128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + goto selectRem; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + do { + altRem = rem; + ++q; + rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0); + } while (! (rem.v64 & UINT64_C(0x8000000000000000))); + selectRem: + meanRem = softfloat_add128(rem.v64, rem.v0, altRem.v64, altRem.v0); + if ((meanRem.v64 & UINT64_C(0x8000000000000000)) || (! (meanRem.v64 | meanRem.v0) && (q & 1))) { + rem = altRem; + } + signRem = signA; + if (rem.v64 & UINT64_C(0x8000000000000000)) { + signRem = ! signRem; + rem = softfloat_sub128(0, 0, rem.v64, rem.v0); + } + return softfloat_normRoundPackToExtF80(signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + copyA: + if (expA < 1) { + sigA >>= 1 - expA; + expA = 0; + } + return packToExtF80(signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/extF80_roundToInt.cc b/src/cpu/softfloat3e/extF80_roundToInt.cc new file mode 100644 index 0000000000..f71cdfc50e --- /dev/null +++ b/src/cpu/softfloat3e/extF80_roundToInt.cc @@ -0,0 +1,123 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + extF80_roundToInt(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64, signUI64; + int32_t exp; + uint64_t sigA; + uint16_t uiZ64; + uint64_t sigZ; + uint64_t lastBitMask, roundBitsMask; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + signUI64 = uiA64 & packToExtF80UI64(1, 0); + exp = expExtF80UI64(uiA64); + sigA = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x403E <= exp) { + if ((exp == 0x7FFF) && (uint64_t) (sigA<<1)) { + return softfloat_propagateNaNExtF80UI(uiA64, sigA, 0, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp <= 0x3FFE) { + if (! exp) { + if ((sigA<<1) == 0) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + switch (roundingMode) { + case softfloat_round_near_even: + if (!(sigA & UINT64_C(0x7FFFFFFFFFFFFFFF))) break; + case softfloat_round_near_maxMag: + if (exp == 0x3FFE) goto mag1; + break; + case softfloat_round_min: + if (signUI64) goto mag1; + break; + case softfloat_round_max: + if (!signUI64) goto mag1; + break; + } + return packToExtF80(signUI64, 0, 0); + mag1: + softfloat_setRoundingUp(status); + return packToExtF80(signUI64, 0x3FFF, UINT64_C(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = signUI64 | exp; + lastBitMask = (uint64_t) 1<<(0x403E - exp); + roundBitsMask = lastBitMask - 1; + sigZ = sigA; + if (roundingMode == softfloat_round_near_maxMag) { + sigZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + sigZ += lastBitMask>>1; + if (!(sigZ & roundBitsMask)) sigZ &= ~lastBitMask; + } else if (roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)) { + sigZ += roundBitsMask; + } + sigZ &= ~roundBitsMask; + if (!sigZ) { + ++uiZ64; + sigZ = UINT64_C(0x8000000000000000); + softfloat_setRoundingUp(status); + } + if (sigZ != sigA) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sigZ > sigA) + softfloat_setRoundingUp(status); + } + return packToExtF80_twoargs(uiZ64, sigZ); +} diff --git a/src/cpu/softfloat3e/extF80_scale.cc b/src/cpu/softfloat3e/extF80_scale.cc new file mode 100644 index 0000000000..48bd53afd4 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_scale.cc @@ -0,0 +1,136 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Scales extended double-precision floating-point value in operand `a' by +| value `b'. The function truncates the value in the second operand 'b' to +| an integral value and adds that value to the exponent of the operand 'a'. +| The operation performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +extFloat80_t extF80_scale(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + uint16_t uiB64; + uint64_t uiB0; + bool signB; + int32_t expB; + uint64_t sigB; + struct exp32_sig64 normExpSig; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { +invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + uiB64 = b.signExp; + uiB0 = b.signif; + signB = signExtF80UI64(uiB64); + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + + if (expA == 0x7FFF) { + if ((sigA<<1) || ((expB == 0x7FFF) && (sigB<<1))) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + } + if ((expB == 0x7FFF) && signB) goto invalid; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return a; + } + if (expB == 0x7FFF) { + if (sigB<<1) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); + } + if ((expA | sigA) == 0) { + if (! signB) goto invalid; + return a; + } + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + if (signB) return packToExtF80(signA, 0, 0); + return packToExtF80(signA, 0x7FFF, BX_CONST64(0x8000000000000000)); + } + if (! expA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + if (expB < 0x3FFF) + return softfloat_normRoundPackToExtF80(signA, expA, sigA, 0, 80, status); + } + if (!expB) { + if (!sigB) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + + if (expB > 0x400E) { + /* generate appropriate overflow/underflow */ + return softfloat_roundPackToExtF80(signA, signB ? -0x3FFF : 0x7FFF, sigA, 0, 80, status); + } + + if (expB < 0x3FFF) return a; + + int shiftCount = 0x403E - expB; + sigB >>= shiftCount; + int32_t scale = (int32_t) sigB; + if (signB) scale = -scale; /* -32768..32767 */ + + return softfloat_roundPackToExtF80(signA, expA + scale, sigA, 0, 80, status); +} diff --git a/src/cpu/softfloat3e/extF80_sqrt.cc b/src/cpu/softfloat3e/extF80_sqrt.cc new file mode 100644 index 0000000000..1a5d52e5dc --- /dev/null +++ b/src/cpu/softfloat3e/extF80_sqrt.cc @@ -0,0 +1,159 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t extF80_sqrt(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool signA; + int32_t expA; + uint64_t sigA; + struct exp32_sig64 normExpSig; + int32_t expZ; + uint32_t sig32A, recipSqrt32, sig32Z; + struct uint128 rem; + uint64_t q, x64, sigZ; + struct uint128 y, term; + uint64_t sigZExtra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) + goto invalid; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + signA = signExtF80UI64(uiA64); + expA = expExtF80UI64(uiA64); + sigA = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if ((expA | sigA) == 0) return packToExtF80(signA, 0, 0); + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + expA = 1; + if (sigA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + if (! (sigA & UINT64_C(0x8000000000000000))) { + if (! sigA) return packToExtF80(signA, 0, 0); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA += normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FFF)>>1) + 0x3FFF; + expA &= 1; + sig32A = sigA>>32; + recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A); + sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; + if (expA) { + sig32Z >>= 1; + rem = softfloat_shortShiftLeft128(0, sigA, 61); + } else { + rem = softfloat_shortShiftLeft128(0, sigA, 62); + } + rem.v64 -= (uint64_t) sig32Z * sig32Z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = ((uint32_t) (rem.v64>>2) * (uint64_t) recipSqrt32)>>32; + x64 = (uint64_t) sig32Z<<32; + sigZ = x64 + (q<<3); + y = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + /*------------------------------------------------------------------------ + | (Repeating this loop is a rare occurrence.) + *------------------------------------------------------------------------*/ + for (;;) { + term = softfloat_mul64ByShifted32To128(x64 + sigZ, q); + rem = softfloat_sub128(y.v64, y.v0, term.v64, term.v0); + if (! (rem.v64 & UINT64_C(0x8000000000000000))) break; + --q; + sigZ -= 1<<3; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + q = (((rem.v64>>2) * recipSqrt32)>>32) + 2; + x64 = sigZ; + sigZ = (sigZ<<1) + (q>>25); + sigZExtra = (uint64_t) (q<<39); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((q & 0xFFFFFF) <= 2) { + q &= ~(uint64_t) 0xFFFF; + sigZExtra = (uint64_t) (q<<39); + term = softfloat_mul64ByShifted32To128(x64 + (q>>27), q); + x64 = (uint32_t) (q<<5) * (uint64_t) (uint32_t) q; + term = softfloat_add128(term.v64, term.v0, 0, x64); + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 28); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + if (! sigZExtra) --sigZ; + --sigZExtra; + } else { + if (rem.v64 | rem.v0) sigZExtra |= 1; + } + } + return + softfloat_roundPackToExtF80(0, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); +} diff --git a/src/cpu/softfloat3e/extF80_to_f128.cc b/src/cpu/softfloat3e/extF80_to_f128.cc new file mode 100644 index 0000000000..24e523cac8 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f128.cc @@ -0,0 +1,75 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t extF80_to_f128(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + uint16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + bool sign; + struct uint128 frac128; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + } + + uiA64 = a.signExp; + uiA0 = a.signif; + exp = expExtF80UI64(uiA64); + frac = uiA0 & UINT64_C(0x7FFFFFFFFFFFFFFF); + if ((exp == 0x7FFF) && frac) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF128UI(&commonNaN); + } else { + sign = signExtF80UI64(uiA64); + frac128 = softfloat_shortShiftLeft128(0, frac, 49); + uiZ.v64 = packToF128UI64(sign, exp, frac128.v64); + uiZ.v0 = frac128.v0; + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/extF80_to_f16.cc b/src/cpu/softfloat3e/extF80_to_f16.cc new file mode 100644 index 0000000000..5078e689cc --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f16.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float16 extF80_to_f16(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint16_t uiZ, sig16; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF16UI(&commonNaN); + } else { + uiZ = packToF16UI(sign, 0x1F, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig16 = softfloat_shortShiftRightJam64(sig, 49); + if (! (exp | sig16)) { + return packToF16UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3FF1; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x40) exp = -0x40; + } + return softfloat_roundPackToF16(sign, exp, sig16, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_f32.cc b/src/cpu/softfloat3e/extF80_to_f32.cc new file mode 100644 index 0000000000..558df4c235 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f32.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 extF80_to_f32(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint32_t uiZ, sig32; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = softfloat_shortShiftRightJam64(sig, 33); + if (! (exp | sig32)) { + return packToF32UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3F81; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return softfloat_roundPackToF32(sign, exp, sig32, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_f64.cc b/src/cpu/softfloat3e/extF80_to_f64.cc new file mode 100644 index 0000000000..4ba4174e3c --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_f64.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 extF80_to_f64(extFloat80_t a, struct softfloat_status_t *status) +{ + uint16_t uiA64; + uint64_t uiA0; + bool sign; + int32_t exp; + uint64_t sig; + struct commonNaN commonNaN; + uint64_t uiZ; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + uiA0 = a.signif; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! (exp | sig)) { + return packToF64UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) { + softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = softfloat_shortShiftRightJam64(sig, 1); + exp -= 0x3C01; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return softfloat_roundPackToF64(sign, exp, sig, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_i32.cc b/src/cpu/softfloat3e/extF80_to_i32.cc new file mode 100644 index 0000000000..ea6c94484c --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_i32.cc @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t extF80_to_i32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x4032 - exp; + if (shiftDist <= 0) shiftDist = 1; + sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToI32(sign, sig, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc new file mode 100644 index 0000000000..42415c4599 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_i32_r_minMag.cc @@ -0,0 +1,93 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t extF80_to_i32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + int32_t absZ; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (shiftDist < 33) { + if ((uiA64 == packToExtF80UI64(1, 0x401E)) && (sig < UINT64_C(0x8000000100000000))) { + if (exact && (sig & UINT64_C(0x00000000FFFFFFFF))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + absZ = sig>>shiftDist; + if (exact && ((uint64_t) (uint32_t) absZ< +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t extF80_to_i64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + uint64_t sigExtra; + struct uint64_extra sig64Extra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigExtra = 0; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + } + return softfloat_roundToI64(sign, sig, sigExtra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc new file mode 100644 index 0000000000..3500b20d27 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_i64_r_minMag.cc @@ -0,0 +1,90 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t extF80_to_i64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + int64_t absZ; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (shiftDist <= 0) { + if ((uiA64 == packToExtF80UI64(1, 0x403E)) && (sig == UINT64_C(0x8000000000000000))) { + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + absZ = sig>>shiftDist; + if (exact && (uint64_t) (sig<<(-shiftDist & 63))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return sign ? -absZ : absZ; +} diff --git a/src/cpu/softfloat3e/extF80_to_ui32.cc b/src/cpu/softfloat3e/extF80_to_ui32.cc new file mode 100644 index 0000000000..449cafa884 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_ui32.cc @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t + extF80_to_ui32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x4032 - exp; + if (shiftDist <= 0) shiftDist = 1; + sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToUI32(sign, sig, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc new file mode 100644 index 0000000000..7ef1001390 --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_ui32_r_minMag.cc @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t extF80_to_ui32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + uint32_t z; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (sign || (shiftDist < 32)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + z = sig>>shiftDist; + if (exact && ((uint64_t) z< +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t extF80_to_ui64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + bool sign; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + uint64_t sigExtra; + struct uint64_extra sig64Extra; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + sign = signExtF80UI64(uiA64); + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (shiftDist < 0) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigExtra = 0; + if (shiftDist) { + sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + } + return softfloat_roundToUI64(sign, sig, sigExtra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc b/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc new file mode 100644 index 0000000000..78b058754d --- /dev/null +++ b/src/cpu/softfloat3e/extF80_to_ui64_r_minMag.cc @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t extF80_to_ui64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status) +{ + uint16_t uiA64; + int32_t exp; + uint64_t sig; + int32_t shiftDist; + bool sign; + uint64_t z; + + // handle unsupported extended double-precision floating encodings + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui64_fromNaN; + } + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.signExp; + exp = expExtF80UI64(uiA64); + sig = a.signif; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x403E - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signExtF80UI64(uiA64); + if (sign || (shiftDist < 0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + z = sig>>shiftDist; + if (exact && (z< +#include +#include "internals.h" +#include "softfloat.h" + +extern float128_t + softfloat_addMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *); +extern float128_t + softfloat_subMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *); + +float128_t f128_add(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + uint64_t uiB64, uiB0; + bool signB; + + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + + if (signA == signB) { + return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} + +float128_t f128_sub(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + uint64_t uiB64, uiB0; + bool signB; + + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + + if (signA == signB) { + return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } else { + return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status); + } +} diff --git a/src/cpu/softfloat3e/f128_div.cc b/src/cpu/softfloat3e/f128_div.cc new file mode 100644 index 0000000000..837eb15aa0 --- /dev/null +++ b/src/cpu/softfloat3e/f128_div.cc @@ -0,0 +1,187 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_div(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + int32_t expA; + struct uint128 sigA; + uint64_t uiB64, uiB0; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signZ; + struct exp32_sig128 normExpSig; + int32_t expZ; + struct uint128 rem; + uint32_t recip32; + int ix; + uint64_t q64; + uint32_t q; + struct uint128 term; + uint32_t qs[3]; + uint64_t sigZExtra; + struct uint128 sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0) goto propagateNaN; + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + goto invalid; + } + goto infinity; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! (sigB.v64 | sigB.v0)) { + if (! (expA | sigA.v64 | sigA.v0)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FFE; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB.v64 |= UINT64_C(0x0001000000000000); + rem = sigA; + if (softfloat_lt128(sigA.v64, sigA.v0, sigB.v64, sigB.v0)) { + --expZ; + rem = softfloat_add128(sigA.v64, sigA.v0, sigA.v64, sigA.v0); + } + recip32 = softfloat_approxRecip32_1(sigB.v64>>17); + ix = 3; + for (;;) { + q64 = (uint64_t) (uint32_t) (rem.v64>>19) * recip32; + q = (q64 + 0x80000000)>>32; + --ix; + if (ix < 0) break; + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul128By32(sigB.v64, sigB.v0, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, sigB.v64, sigB.v0); + } + qs[ix] = q; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (((q + 1) & 7) < 2) { + rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29); + term = softfloat_mul128By32(sigB.v64, sigB.v0, q); + rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0); + if (rem.v64 & UINT64_C(0x8000000000000000)) { + --q; + rem = softfloat_add128(rem.v64, rem.v0, sigB.v64, sigB.v0); + } else if (softfloat_le128(sigB.v64, sigB.v0, rem.v64, rem.v0)) { + ++q; + rem = softfloat_sub128(rem.v64, rem.v0, sigB.v64, sigB.v0); + } + if (rem.v64 | rem.v0) q |= 1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZExtra = (uint64_t) ((uint64_t) q<<60); + term = softfloat_shortShiftLeft128(0, qs[1], 54); + sigZ = softfloat_add128((uint64_t) qs[2]<<19, ((uint64_t) qs[0]<<25) + (q>>4), term.v64, term.v0); + return + softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ.v64 = packToF128UI64(signZ, 0, 0); + uiZ.v0 = 0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_mul.cc b/src/cpu/softfloat3e/f128_mul.cc new file mode 100644 index 0000000000..fd63a4590a --- /dev/null +++ b/src/cpu/softfloat3e/f128_mul.cc @@ -0,0 +1,148 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "primitiveTypes.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f128_mul(float128_t a, float128_t b, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool signA; + int32_t expA; + struct uint128 sigA; + uint64_t uiB64, uiB0; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signZ; + uint64_t magBits; + struct exp32_sig128 normExpSig; + int32_t expZ; + uint64_t sig256Z[4]; + uint64_t sigZExtra; + struct uint128 sigZ; + struct uint128_extra sig128Extra; + struct uint128 uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + uiB64 = b.v64; + uiB0 = b.v0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) { + goto propagateNaN; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infArg; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + magBits = expA | sigA.v64 | sigA.v0; + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! (sigB.v64 | sigB.v0)) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x4000; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 16); + softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z); + sigZExtra = sig256Z[indexWord(4, 1)] | (sig256Z[indexWord(4, 0)] != 0); + sigZ = softfloat_add128(sig256Z[indexWord(4, 3)], sig256Z[indexWord(4, 2)], sigA.v64, sigA.v0); + if (UINT64_C(0x0002000000000000) <= sigZ.v64) { + ++expZ; + sig128Extra = softfloat_shortShiftRightJam128Extra(sigZ.v64, sigZ.v0, sigZExtra, 1); + sigZ = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } + return + softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + } + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + uiZ.v64 = packToF128UI64(signZ, 0, 0); + uiZ.v0 = 0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_mulAdd.cc b/src/cpu/softfloat3e/f128_mulAdd.cc new file mode 100644 index 0000000000..749342f5f1 --- /dev/null +++ b/src/cpu/softfloat3e/f128_mulAdd.cc @@ -0,0 +1,332 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "primitiveTypes.h" +#include "softfloat.h" +#include "specialize.h" + +float128_t f128_mulAdd(float128_t a, float128_t b, float128_t c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int32_t expA; + struct uint128 sigA; + bool signB; + int32_t expB; + struct uint128 sigB; + bool signC; + int32_t expC; + struct uint128 sigC; + bool signZ; + uint64_t magBits; + struct uint128 uiZ; + struct exp32_sig128 normExpSig; + int32_t expZ; + uint64_t sig256Z[4]; + struct uint128 sigZ; + int32_t shiftDist, expDiff; + struct uint128 x128; + uint64_t sig256C[4]; + static uint64_t zero256[4] = INIT_UINTM4(0, 0, 0, 0); + uint64_t sigZExtra, sig256Z0; + uint64_t uiA64, uiA0; + uint64_t uiB64, uiB0; + uint64_t uiC64, uiC0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + uiB64 = b.v64; + uiB0 = b.v0; + uiC64 = c.v64; + uiC0 = c.v0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF128UI64(uiA64); + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + signB = signF128UI64(uiB64); + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + signC = signF128UI64(uiC64) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF128UI64(uiC64); + sigC.v64 = fracF128UI64(uiC64); + sigC.v0 = uiC0; + signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) { + goto propagateNaN_ABC; + } + magBits = expB | sigB.v64 | sigB.v0; + goto infProdArg; + } + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN_ABC; + magBits = expA | sigA.v64 | sigA.v0; + goto infProdArg; + } + if (expC == 0x7FFF) { + if (sigC.v64 | sigC.v0) { + uiZ.v64 = 0; + uiZ.v0 = 0; + goto propagateNaN_ZC; + } + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! (sigA.v64 | sigA.v0)) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! (sigB.v64 | sigB.v0)) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FFE; + sigA.v64 |= UINT64_C(0x0001000000000000); + sigB.v64 |= UINT64_C(0x0001000000000000); + sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 8); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 15); + softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z); + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + shiftDist = 0; + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = -1; + } + if (! expC) { + if (! (sigC.v64 | sigC.v0)) { + shiftDist += 8; + goto sigZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(sigC.v64, sigC.v0); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC.v64 |= UINT64_C(0x0001000000000000); + sigC = softfloat_shortShiftLeft128(sigC.v64, sigC.v0, 8); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if (expDiff < 0) { + expZ = expC; + if ((signZ == signC) || (expDiff < -1)) { + shiftDist -= expDiff; + if (shiftDist) { + sigZ = softfloat_shiftRightJam128(sigZ.v64, sigZ.v0, shiftDist); + } + } else { + if (! shiftDist) { + x128 = softfloat_shortShiftRight128(sig256Z[indexWord(4, 1)], sig256Z[indexWord(4, 0)], 1); + sig256Z[indexWord(4, 1)] = (sigZ.v0<<63) | x128.v64; + sig256Z[indexWord(4, 0)] = x128.v0; + sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, 1); + sig256Z[indexWord(4, 3)] = sigZ.v64; + sig256Z[indexWord(4, 2)] = sigZ.v0; + } + } + } else { + if (shiftDist) softfloat_add256M(sig256Z, sig256Z, sig256Z); + if (! expDiff) { + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + } else { + sig256C[indexWord(4, 3)] = sigC.v64; + sig256C[indexWord(4, 2)] = sigC.v0; + sig256C[indexWord(4, 1)] = 0; + sig256C[indexWord(4, 0)] = 0; + softfloat_shiftRightJam256M(sig256C, expDiff, sig256C); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 8; + if (signZ == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + sigZ = softfloat_add128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); + } else { + softfloat_add256M(sig256Z, sig256C, sig256Z); + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + } + if (sigZ.v64 & UINT64_C(0x0200000000000000)) { + ++expZ; + shiftDist = 9; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + signZ = signC; + if (expDiff < -1) { + sigZ = softfloat_sub128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0); + sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; + if (sigZExtra) { + sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1); + } + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = 7; + } + goto shiftRightRoundPack; + } else { + sig256C[indexWord(4, 3)] = sigC.v64; + sig256C[indexWord(4, 2)] = sigC.v0; + sig256C[indexWord(4, 1)] = 0; + sig256C[indexWord(4, 0)] = 0; + softfloat_sub256M(sig256C, sig256Z, sig256Z); + } + } else if (! expDiff) { + sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, sigC.v64, sigC.v0); + if (! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord(4, 1)] && ! sig256Z[indexWord(4, 0)]) { + goto completeCancellation; + } + sig256Z[indexWord(4, 3)] = sigZ.v64; + sig256Z[indexWord(4, 2)] = sigZ.v0; + if (sigZ.v64 & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + softfloat_sub256M(zero256, sig256Z, sig256Z); + } + } else { + softfloat_sub256M(sig256Z, sig256C, sig256Z); + if (1 < expDiff) { + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) { + --expZ; + shiftDist = 7; + } + goto sigZ; + } + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigZ.v64 = sig256Z[indexWord(4, 3)]; + sigZ.v0 = sig256Z[indexWord(4, 2)]; + sigZExtra = sig256Z[indexWord(4, 1)]; + sig256Z0 = sig256Z[indexWord(4, 0)]; + if (sigZ.v64) { + if (sig256Z0) sigZExtra |= 1; + } else { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = sig256Z0; + if (! sigZ.v64) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = sigZExtra; + sigZExtra = 0; + if (! sigZ.v64) { + expZ -= 64; + sigZ.v64 = sigZ.v0; + sigZ.v0 = 0; + } + } + } + shiftDist = softfloat_countLeadingZeros64(sigZ.v64); + expZ += 7 - shiftDist; + shiftDist = 15 - shiftDist; + if (0 < shiftDist) goto shiftRightRoundPack; + if (shiftDist) { + shiftDist = -shiftDist; + sigZ = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, shiftDist); + x128 = softfloat_shortShiftLeft128(0, sigZExtra, shiftDist); + sigZ.v0 |= x128.v64; + sigZExtra = x128.v0; + } + goto roundPack; + } + sigZ: + sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)]; + shiftRightRoundPack: + sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0); + sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, shiftDist); + roundPack: + return softfloat_roundPackToF128(signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN_ABC: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + goto propagateNaN_ZC; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if ((sigC.v64 | sigC.v0) && expC == 0x7FFF) goto propagateNaN_ZC; + if (magBits) { + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + if (expC != 0x7FFF) return uiZ; + if (signZ == signC) return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + propagateNaN_ZC: + uiZ = softfloat_propagateNaNF128UI(uiZ.v64, uiZ.v0, uiC64, uiC0, status); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ.v64 = uiC64; + uiZ.v0 = uiC0; + if (! (expC | sigC.v64 | sigC.v0) && (signZ != signC)) { + completeCancellation: + uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + uiZ.v0 = 0; + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_roundToInt.cc b/src/cpu/softfloat3e/f128_roundToInt.cc new file mode 100644 index 0000000000..c3b7287040 --- /dev/null +++ b/src/cpu/softfloat3e/f128_roundToInt.cc @@ -0,0 +1,142 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + f128_roundToInt(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + int32_t exp; + struct uint128 uiZ; + uint64_t lastBitMask0, roundBitsMask; + bool roundNearEven; + uint64_t lastBitMask64; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + exp = expF128UI64(uiA64); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x402F <= exp) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (0x406F <= exp) { + if ((exp == 0x7FFF) && (fracF128UI64(uiA64) | uiA0)) { + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, 0, 0, status); + return uiZ; + } + return a; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + lastBitMask0 = (uint64_t) 2<<(0x406E - exp); + roundBitsMask = lastBitMask0 - 1; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + roundNearEven = (roundingMode == softfloat_round_near_even); + if (roundNearEven || (roundingMode == softfloat_round_near_maxMag)) { + if (exp == 0x402F) { + if (UINT64_C(0x8000000000000000) <= uiZ.v0) { + ++uiZ.v64; + if (roundNearEven && (uiZ.v0 == UINT64_C(0x8000000000000000))) { + uiZ.v64 &= ~1; + } + } + } else { + uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, lastBitMask0>>1); + if (roundNearEven && !(uiZ.v0 & roundBitsMask)) { + uiZ.v0 &= ~lastBitMask0; + } + } + } else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) { + uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, roundBitsMask); + } + uiZ.v0 &= ~roundBitsMask; + lastBitMask64 = !lastBitMask0; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (exp < 0x3FFF) { + if (!((uiA64 & UINT64_C(0x7FFFFFFFFFFFFFFF)) | uiA0)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ.v64 = uiA64 & packToF128UI64(1, 0, 0); + uiZ.v0 = 0; + switch (roundingMode) { + case softfloat_round_near_even: + if (!(fracF128UI64(uiA64) | uiA0)) break; + case softfloat_round_near_maxMag: + if (exp == 0x3FFE) uiZ.v64 |= packToF128UI64(0, 0x3FFF, 0); + break; + case softfloat_round_min: + if (uiZ.v64) uiZ.v64 = packToF128UI64(1, 0x3FFF, 0); + break; + case softfloat_round_max: + if (!uiZ.v64) uiZ.v64 = packToF128UI64(0, 0x3FFF, 0); + break; + } + return uiZ; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + uiZ.v64 = uiA64; + uiZ.v0 = 0; + lastBitMask64 = (uint64_t) 1<<(0x402F - exp); + roundBitsMask = lastBitMask64 - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ.v64 += lastBitMask64>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ.v64 += lastBitMask64>>1; + if (!((uiZ.v64 & roundBitsMask) | uiA0)) { + uiZ.v64 &= ~lastBitMask64; + } + } else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) { + uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask; + } + uiZ.v64 &= ~roundBitsMask; + lastBitMask0 = 0; + } + if ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f128_to_extF80.cc b/src/cpu/softfloat3e/f128_to_extF80.cc new file mode 100644 index 0000000000..916820bc9d --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_extF80.cc @@ -0,0 +1,94 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f128_to_extF80(float128_t a, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t frac64, frac0; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp32_sig128 normExpSig; + struct uint128 sig128; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + frac64 = fracF128UI64(uiA64); + frac0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (frac64 | frac0) { + softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! (frac64 | frac0)) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF128Sig(frac64, frac0); + exp = normExpSig.exp; + frac64 = normExpSig.sig.v64; + frac0 = normExpSig.sig.v0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig128 = softfloat_shortShiftLeft128(frac64 | UINT64_C(0x0001000000000000), frac0, 15); + return softfloat_roundPackToExtF80(sign, exp, sig128.v64, sig128.v0, 80, status); +} diff --git a/src/cpu/softfloat3e/f128_to_f32.cc b/src/cpu/softfloat3e/f128_to_f32.cc new file mode 100644 index 0000000000..485d68a0ce --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_f32.cc @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f128_to_f32(float128_t a, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t frac64; + struct commonNaN commonNaN; + uint32_t uiZ, frac32; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + frac64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (frac64) { + softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac32 = softfloat_shortShiftRightJam64(frac64, 18); + if (! (exp | frac32)) { + return packToF32UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3F81; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return softfloat_roundPackToF32(sign, exp, frac32 | 0x40000000, status); +} diff --git a/src/cpu/softfloat3e/f128_to_f64.cc b/src/cpu/softfloat3e/f128_to_f64.cc new file mode 100644 index 0000000000..0809c7102c --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_f64.cc @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f128_to_f64(float128_t a, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t frac64, frac0; + struct commonNaN commonNaN; + uint64_t uiZ; + struct uint128 frac128; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + frac64 = fracF128UI64(uiA64); + frac0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FFF) { + if (frac64 | frac0) { + softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac128 = softfloat_shortShiftLeft128(frac64, frac0, 14); + frac64 = frac128.v64 | (frac128.v0 != 0); + if (! (exp | frac64)) { + return packToF64UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp -= 0x3C01; + if (sizeof (int16_t) < sizeof (int32_t)) { + if (exp < -0x1000) exp = -0x1000; + } + return + softfloat_roundPackToF64(sign, exp, frac64 | UINT64_C(0x4000000000000000), status); +} diff --git a/src/cpu/softfloat3e/f128_to_i32.cc b/src/cpu/softfloat3e/f128_to_i32.cc new file mode 100644 index 0000000000..68cf2b3a70 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_i32.cc @@ -0,0 +1,80 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f128_to_i32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0x7FFF) && (sig64 | sig0)) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + sig64 |= (sig0 != 0); + shiftDist = 0x4023 - exp; + if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + return softfloat_roundToI32(sign, sig64, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc b/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc new file mode 100644 index 0000000000..a62233d4df --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_i32_r_minMag.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f128_to_i32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + int32_t exp; + uint64_t sig64; + int32_t shiftDist; + bool sign; + int32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (49 <= shiftDist) { + if (exact && (exp | sig64)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF128UI64(uiA64); + if (shiftDist < 18) { + if (sign && (shiftDist == 17) && (sig64 < UINT64_C(0x0000000000020000))) { + if (exact && sig64) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && sig64 ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + absZ = sig64>>shiftDist; + if (exact && ((uint64_t) (uint32_t) absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f128_to_i64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + struct uint128 sig128; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -15) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig64, sig0, -shiftDist); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + sigExtra = softfloat_shiftRightJam64Extra(sig64, sig0, shiftDist); + sig64 = sigExtra.v; + sig0 = sigExtra.extra; + } + return softfloat_roundToI64(sign, sig64, sig0, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc b/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc new file mode 100644 index 0000000000..edeccf1828 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_i64_r_minMag.cc @@ -0,0 +1,104 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f128_to_i64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + int8_t negShiftDist; + uint64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist < 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -14) { + if ((uiA64 == UINT64_C(0xC03E000000000000)) && (sig0 < UINT64_C(0x0002000000000000))) { + if (exact && sig0) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FFF) && (sig64 | sig0) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + negShiftDist = -shiftDist; + absZ = sig64<>(shiftDist & 63); + if (exact && (uint64_t) (sig0<>shiftDist; + if (exact && (sig0 || (absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f128_to_ui32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64; + int32_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0x7FFF) && sig64) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + shiftDist = 0x4023 - exp; + if (0 < shiftDist) { + sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + } + return softfloat_roundToUI32(sign, sig64, roundingMode, exact, status); +} + diff --git a/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc b/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc new file mode 100644 index 0000000000..96007f6a1d --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_ui32_r_minMag.cc @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f128_to_ui32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + int32_t exp; + uint64_t sig64; + int32_t shiftDist; + bool sign; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64) | (uiA0 != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (49 <= shiftDist) { + if (exact && (exp | sig64)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF128UI64(uiA64); + if (sign || (shiftDist < 17)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && sig64 ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + z = sig64>>shiftDist; + if (exact && ((uint64_t) z< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f128_to_ui64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + struct uint128 sig128; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -15) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64 |= UINT64_C(0x0001000000000000); + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig64, sig0, -shiftDist); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (exp) sig64 |= UINT64_C(0x0001000000000000); + sigExtra = softfloat_shiftRightJam64Extra(sig64, sig0, shiftDist); + sig64 = sigExtra.v; + sig0 = sigExtra.extra; + } + return softfloat_roundToUI64(sign, sig64, sig0, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc b/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc new file mode 100644 index 0000000000..8d30420b02 --- /dev/null +++ b/src/cpu/softfloat3e/f128_to_ui64_r_minMag.cc @@ -0,0 +1,99 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f128_to_ui64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status) +{ + uint64_t uiA64, uiA0; + bool sign; + int32_t exp; + uint64_t sig64, sig0; + int32_t shiftDist; + int8_t negShiftDist; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA64 = a.v64; + uiA0 = a.v0; + sign = signF128UI64(uiA64); + exp = expF128UI64(uiA64); + sig64 = fracF128UI64(uiA64); + sig0 = uiA0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x402F - exp; + if (shiftDist < 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (sign || (shiftDist < -15)) goto invalid; + sig64 |= UINT64_C(0x0001000000000000); + negShiftDist = -shiftDist; + z = sig64<>(shiftDist & 63); + if (exact && (uint64_t) (sig0<>shiftDist; + if (exact && (sig0 || (z< +#include +#include "internals.h" +#include "softfloat.h" + +extern float16 softfloat_addMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); +extern float16 softfloat_subMagsF16(uint16_t, uint16_t, struct softfloat_status_t *); + +float16 f16_add(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (signF16UI((uint16_t) a ^ (uint16_t) b)) { + return softfloat_subMagsF16(a, b, status); + } else { + return softfloat_addMagsF16(a, b, status); + } +} + +float16 f16_sub(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (signF16UI((uint16_t) a ^ (uint16_t) b)) { + return softfloat_addMagsF16(a, b, status); + } else { + return softfloat_subMagsF16(a, b, status); + } +} diff --git a/src/cpu/softfloat3e/f16_class.c b/src/cpu/softfloat3e/f16_class.c new file mode 100644 index 0000000000..b375c1544e --- /dev/null +++ b/src/cpu/softfloat3e/f16_class.c @@ -0,0 +1,64 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t f16_class(float16 a) +{ + bool signA; + int8_t expA; + uint16_t sigA; + + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + + if (expA == 0x1F) { + if (sigA == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & 0x200) ? softfloat_QNaN : softfloat_SNaN; + } + + if (expA == 0) { + if (sigA == 0) return softfloat_zero; + return softfloat_denormal; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/f16_compare.c b/src/cpu/softfloat3e/f16_compare.c new file mode 100644 index 0000000000..1cfd56bec9 --- /dev/null +++ b/src/cpu/softfloat3e/f16_compare.c @@ -0,0 +1,92 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two half precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int f16_compare(float16 a, float16 b, bool quiet, struct softfloat_status_t *status) +{ + softfloat_class_t aClass; + softfloat_class_t bClass; + bool signA; + bool signB; + + aClass = f16_class(a); + bClass = f16_class(b); + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + a = a & 0x8000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if (bClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + b = b & 0x8000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if ((a == b) || ((uint16_t) ((a | b)<<1) == 0)) return softfloat_relation_equal; + + signA = signF16UI(a); + signB = signF16UI(b); + if (signA != signB) + return (signA) ? softfloat_relation_less : softfloat_relation_greater; + + if (signA ^ (a < b)) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/f16_div.c b/src/cpu/softfloat3e/f16_div.c new file mode 100644 index 0000000000..c91760b03b --- /dev/null +++ b/src/cpu/softfloat3e/f16_div.c @@ -0,0 +1,149 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#define SOFTFLOAT_FAST_DIV32TO16 1 + +extern const uint16_t softfloat_approxRecip_1k0s[]; +extern const uint16_t softfloat_approxRecip_1k1s[]; + +float16 f16_div(float16 a, float16 b, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signZ; + struct exp8_sig16 normExpSig; + int8_t expZ; +#ifdef SOFTFLOAT_FAST_DIV32TO16 + uint32_t sig32A; + uint16_t sigZ; +#endif + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + signB = signF16UI(b); + expB = expF16UI(b); + sigB = fracF16UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA) goto propagateNaN; + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + goto invalid; + } + if (sigB && !expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infinity; + } + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + if (sigA && !expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) { + if (! (expA | sigA)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! sigA) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0xE; + sigA |= 0x0400; + sigB |= 0x0400; +#ifdef SOFTFLOAT_FAST_DIV32TO16 + if (sigA < sigB) { + --expZ; + sig32A = (uint32_t) sigA<<15; + } else { + sig32A = (uint32_t) sigA<<14; + } + sigZ = sig32A / sigB; + if (! (sigZ & 7)) sigZ |= ((uint32_t) sigB * sigZ != sig32A); +#endif + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + return packToF16UI(signZ, 0x1F, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF16UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f16_getExp.c b/src/cpu/softfloat3e/f16_getExp.c new file mode 100644 index 0000000000..dfade995f7 --- /dev/null +++ b/src/cpu/softfloat3e/f16_getExp.c @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of half-precision floating-point value 'a', +| and returns the result as a half-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float16 f16_getExp(float16 a, struct softfloat_status_t *status) +{ + int8_t expA; + uint16_t sigA; + struct exp8_sig16 normExpSig; + + expA = expF16UI(a); + sigA = fracF16UI(a); + + if (expA == 0x1F) { + if (sigA) return softfloat_propagateNaNF16UI(a, 0, status); + return (float16)packToF32UI(0, 0x1F, 0); + } + + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return (float16)packToF32UI(1, 0x1F, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + } + + return i32_to_f16((int32_t)(expA) - 0xF, status); +} diff --git a/src/cpu/softfloat3e/f16_getMant.c b/src/cpu/softfloat3e/f16_getMant.c new file mode 100644 index 0000000000..f0d8d54821 --- /dev/null +++ b/src/cpu/softfloat3e/f16_getMant.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of half-precision floating-point value 'a' and +| returns the result as a half-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float16 f16_getMant(float16 a, struct softfloat_status_t *status, int sign_ctrl, int interv) +{ + bool signA; + int8_t expA; + uint16_t sigA; + struct exp8_sig16 normExpSig; + + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + + if (expA == 0x1F) { + if (sigA) return softfloat_propagateNaNF16UI(a, 0, status); + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + } + return packToF16UI(~sign_ctrl & signA, 0x1F, 0); + } + + if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) { + return packToF16UI(~sign_ctrl & signA, 0x1F, 0); + } + + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + } + + if (expA == 0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + sigA &= 0x3ff; + } + + switch(interv) { + case 0x0: // interval [1,2) + expA = 0xF; + break; + case 0x1: // interval [1/2,2) + expA -= 0xF; + expA = 0xF - (expA & 0x1); + break; + case 0x2: // interval [1/2,1) + expA = 0xE; + break; + case 0x3: // interval [3/4,3/2) + expA = 0xF - ((sigA >> 9) & 0x1); + break; + } + + return packToF16UI(~sign_ctrl & signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/f16_minmax.c b/src/cpu/softfloat3e/f16_minmax.c new file mode 100644 index 0000000000..11922a1ba2 --- /dev/null +++ b/src/cpu/softfloat3e/f16_minmax.c @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two half precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float16 f16_min(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f16_denormal_to_zero(a); + b = f16_denormal_to_zero(b); + } + + return (f16_compare_normal(a, b, status) == softfloat_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two half precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float16 f16_max(float16 a, float16 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f16_denormal_to_zero(a); + b = f16_denormal_to_zero(b); + } + + return (f16_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b; +} diff --git a/src/cpu/softfloat3e/f16_mul.c b/src/cpu/softfloat3e/f16_mul.c new file mode 100644 index 0000000000..2e7e74826a --- /dev/null +++ b/src/cpu/softfloat3e/f16_mul.c @@ -0,0 +1,139 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f16_mul(float16 a, float16 b, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signZ; + uint16_t magBits; + struct exp8_sig16 normExpSig; + int8_t expZ; + uint32_t sig32Z; + uint16_t sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + signB = signF16UI(b); + expB = expF16UI(b); + sigB = fracF16UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA || ((expB == 0x1F) && sigB)) goto propagateNaN; + magBits = expB | sigB; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + magBits = expA | sigA; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0xF; + sigA = (sigA | 0x0400)<<4; + sigB = (sigB | 0x0400)<<5; + sig32Z = (uint32_t) sigA * sigB; + sigZ = sig32Z>>16; + if (sig32Z & 0xFFFF) sigZ |= 1; + if (sigZ < 0x4000) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF16UI; + } else { + uiZ = packToF16UI(signZ, 0x1F, 0); + } + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF16UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f16_mulAdd.c b/src/cpu/softfloat3e/f16_mulAdd.c new file mode 100644 index 0000000000..0e630a9b7c --- /dev/null +++ b/src/cpu/softfloat3e/f16_mulAdd.c @@ -0,0 +1,232 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" +#include "specialize.h" + +float16 f16_mulAdd(float16 a, float16 b, float16 c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool signC; + int8_t expC; + uint16_t sigC; + bool signProd; + uint16_t magBits, uiA, uiB, uiC, uiZ; + struct exp8_sig16 normExpSig; + int8_t expProd; + uint32_t sigProd; + bool signZ; + int8_t expZ; + uint16_t sigZ; + int8_t expDiff; + uint32_t sig32Z, sig32C; + int8_t shiftDist; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(uiA); + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + signB = signF16UI(uiB); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + signC = signF16UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF16UI(uiC); + sigC = fracF16UI(uiC); + signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0x1F) && sigA; + bool bisNaN = (expB == 0x1F) && sigB; + bool cisNaN = (expC == 0x1F) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF16UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF16UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0x1F) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0x1F) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF16UI(signC, 0x1F, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0xE; + sigA = (sigA | 0x0400)<<4; + sigB = (sigB | 0x0400)<<4; + sigProd = (uint32_t) sigA * sigB; + if (sigProd < 0x20000000) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if (! expC) { + if (! sigC) { + expZ = expProd - 1; + sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x0400)<<3; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if (signProd == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam32(sigProd, 16 - expDiff); + } else { + expZ = expProd; + sig32Z = sigProd + softfloat_shiftRightJam32((uint32_t) sigC<<16, expDiff); + sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0); + } + if (sigZ < 0x4000) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig32C = (uint32_t) sigC<<16; + if (expDiff < 0) { + signZ = signC; + expZ = expC; + sig32Z = sig32C - softfloat_shiftRightJam32(sigProd, -expDiff); + } else if (! expDiff) { + expZ = expProd; + sig32Z = sigProd - sig32C; + if (! sig32Z) goto completeCancellation; + if (sig32Z & 0x80000000) { + signZ = ! signZ; + sig32Z = -sig32Z; + } + } else { + expZ = expProd; + sig32Z = sigProd - softfloat_shiftRightJam32(sig32C, expDiff); + } + shiftDist = softfloat_countLeadingZeros32(sig32Z) - 1; + expZ -= shiftDist; + shiftDist -= 16; + if (shiftDist < 0) { + sigZ = sig32Z>>(-shiftDist) | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0); + } else { + sigZ = (uint16_t) sig32Z< +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f16_range(float16 a, float16 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + bool signB; + int8_t expB; + uint16_t sigB; + bool aIsNaN, bIsNaN; + uint16_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + signB = signF16UI(b); + expB = expF16UI(b); + sigB = fracF16UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_isSigNaNF16UI(a)) { + return softfloat_propagateNaNF16UI(a, 0, status); + } + if (softfloat_isSigNaNF16UI(b)) { + return softfloat_propagateNaNF16UI(b, 0, status); + } + + aIsNaN = isNaNF16UI(a); + bIsNaN = isNaNF16UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA && sigA) { + if (softfloat_denormalsAreZeros(status)) { + a = packToF16UI(signA, 0, 0); + } + else if (! bIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + + if (! expB && sigB) { + if (softfloat_denormalsAreZeros(status)) { + b = packToF16UI(signB, 0, 0); + } + else if (! aIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (bIsNaN) { + z = a; + } + else if (aIsNaN) { + z = b; + } + else if (signA != signB && ! is_abs) { + if (! is_max) { + z = signA ? a : b; + } else { + z = signA ? b : a; + } + } else { + float16 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a = tmp_a & ~0x8000; // clear the sign bit + tmp_b = tmp_b & ~0x8000; + signA = 0; + } + + if (! is_max) { + z = (signA ^ (tmp_a < tmp_b)) ? a : b; + } else { + z = (signA ^ (tmp_a < tmp_b)) ? b : a; + } + } + + switch(sign_ctrl) { + case 0: + z = (z & ~0x8000) | (a & 0x8000); // keep sign of a + break; + case 1: + break; // preserve sign of compare result + case 2: + z = z & ~0x8000; // zero out the sign bit + break; + case 3: + z = z | 0x8000; // set the sign bit + break; + } + + return z; +} diff --git a/src/cpu/softfloat3e/f16_roundToInt.c b/src/cpu/softfloat3e/f16_roundToInt.c new file mode 100644 index 0000000000..ee9be0c0b3 --- /dev/null +++ b/src/cpu/softfloat3e/f16_roundToInt.c @@ -0,0 +1,112 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f16_roundToInt(float16 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + bool sign; + uint16_t uiZ, lastBitMask, roundBitsMask; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + scale &= 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + sign = signF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x19 <= (exp + scale)) { + if ((exp == 0x1F) && frac) { + return softfloat_propagateNaNF16UI(a, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!exp) { + frac = 0; + a = packToF16UI(sign, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((exp + scale) <= 0xE) { + if (!(exp | frac)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ = packToF16UI(sign, 0, 0); + switch (roundingMode) { + case softfloat_round_near_even: + if (!frac) break; + case softfloat_round_near_maxMag: + if ((exp + scale) == 0xE) uiZ |= packToF16UI(0, 0xF - scale, 0); + break; + case softfloat_round_min: + if (uiZ) uiZ = packToF16UI(1, 0xF - scale, 0); + break; + case softfloat_round_max: + if (!uiZ) uiZ = packToF16UI(0, 0xF - scale, 0); + break; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = a; + lastBitMask = (uint16_t) 1<<(0x19 - exp - scale); + roundBitsMask = lastBitMask - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ += lastBitMask>>1; + if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask; + } else if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if (uiZ != a) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f16_sqrt.c b/src/cpu/softfloat3e/f16_sqrt.c new file mode 100644 index 0000000000..f0f8afef19 --- /dev/null +++ b/src/cpu/softfloat3e/f16_sqrt.c @@ -0,0 +1,130 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; + +float16 f16_sqrt(float16 a, struct softfloat_status_t *status) +{ + bool signA; + int8_t expA; + uint16_t sigA; + struct exp8_sig16 normExpSig; + int8_t expZ; + int index; + uint16_t r0; + uint32_t ESqrR0; + uint16_t sigma0; + uint16_t recipSqrt16, sigZ, shiftedSigZ; + uint16_t negRem; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF16UI(a); + expA = expF16UI(a); + sigA = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA) { + return softfloat_propagateNaNF16UI(a, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + a = packToF16UI(signA, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if (! (expA | sigA)) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = ((expA - 0xF)>>1) + 0xE; + expA &= 1; + sigA |= 0x0400; + index = (sigA>>6 & 0xE) + expA; + r0 = softfloat_approxRecipSqrt_1k0s[index] + - (((uint32_t) softfloat_approxRecipSqrt_1k1s[index] * (sigA & 0x7F)) >>11); + ESqrR0 = ((uint32_t) r0 * r0)>>1; + if (expA) ESqrR0 >>= 1; + sigma0 = ~(uint16_t) ((ESqrR0 * sigA)>>16); + recipSqrt16 = r0 + (((uint32_t) r0 * sigma0)>>25); + if (! (recipSqrt16 & 0x8000)) recipSqrt16 = 0x8000; + sigZ = ((uint32_t) (sigA<<5) * recipSqrt16)>>16; + if (expA) sigZ >>= 1; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + ++sigZ; + if (! (sigZ & 7)) { + shiftedSigZ = sigZ>>1; + negRem = shiftedSigZ * shiftedSigZ; + sigZ &= ~1; + if (negRem & 0x8000) { + sigZ |= 1; + } else { + if (negRem) --sigZ; + } + } + return softfloat_roundPackToF16(0, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; +} diff --git a/src/cpu/softfloat3e/f16_to_extF80.cc b/src/cpu/softfloat3e/f16_to_extF80.cc new file mode 100644 index 0000000000..418be8083d --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_extF80.cc @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f16_to_extF80(float16 a, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp8_sig16 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + if (frac) { + softfloat_f16UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(frac); + exp = normExpSig.exp; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = packToExtF80UI64(sign, exp + 0x3FF0); + uiZ0 = (uint64_t) (frac | 0x0400)<<53; + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/f16_to_f32.c b/src/cpu/softfloat3e/f16_to_f32.c new file mode 100644 index 0000000000..4d862161d8 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_f32.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f16_to_f32(float16 a, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + struct commonNaN commonNaN; + uint32_t uiZ; + struct exp8_sig16 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + if (frac) { + softfloat_f16UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac || softfloat_denormalsAreZeros(status)) { + return packToF32UI(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF32UI(sign, exp + 0x70, (uint32_t) frac<<13); +} diff --git a/src/cpu/softfloat3e/f16_to_f64.c b/src/cpu/softfloat3e/f16_to_f64.c new file mode 100644 index 0000000000..7d61b63577 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_f64.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f16_to_f64(float16 a, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + struct commonNaN commonNaN; + uint64_t uiZ; + struct exp8_sig16 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + if (frac) { + softfloat_f16UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac || softfloat_denormalsAreZeros(status)) { + return packToF64UI(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF16Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF64UI(sign, exp + 0x3F0, (uint64_t) frac<<42); +} diff --git a/src/cpu/softfloat3e/f16_to_i32.c b/src/cpu/softfloat3e/f16_to_i32.c new file mode 100644 index 0000000000..d00cfe2360 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i32.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f16_to_i32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + int32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if (0 <= shiftDist) { + sig32 <<= shiftDist; + return sign ? -sig32 : sig32; + } + shiftDist = exp - 0x0D; + if (0 < shiftDist) sig32 <<= shiftDist; + } + else { + if (softfloat_denormalsAreZeros(status)) sig32 = 0; + } + return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status); +} + diff --git a/src/cpu/softfloat3e/f16_to_i32_r_minMag.c b/src/cpu/softfloat3e/f16_to_i32_r_minMag.c new file mode 100644 index 0000000000..9a6bbdf83b --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i32_r_minMag.c @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f16_to_i32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + int32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (int32_t) (frac | 0x0400)<>= 10; + return sign ? -alignedSig : alignedSig; +} diff --git a/src/cpu/softfloat3e/f16_to_i64.c b/src/cpu/softfloat3e/f16_to_i64.c new file mode 100644 index 0000000000..7dcbeaad80 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i64.c @@ -0,0 +1,80 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f16_to_i64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + int32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if (0 <= shiftDist) { + sig32 <<= shiftDist; + return sign ? -sig32 : sig32; + } + shiftDist = exp - 0x0D; + if (0 < shiftDist) sig32 <<= shiftDist; + } + else { + if (softfloat_denormalsAreZeros(status)) sig32 = 0; + } + return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f16_to_i64_r_minMag.c b/src/cpu/softfloat3e/f16_to_i64_r_minMag.c new file mode 100644 index 0000000000..4289c53525 --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_i64_r_minMag.c @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f16_to_i64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + int32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (int32_t) (frac | 0x0400)<>= 10; + return sign ? -alignedSig : alignedSig; +} diff --git a/src/cpu/softfloat3e/f16_to_ui32.c b/src/cpu/softfloat3e/f16_to_ui32.c new file mode 100644 index 0000000000..d217b2627f --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_ui32.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f16_to_ui32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + uint32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if ((0 <= shiftDist) && ! sign) { + return sig32< +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f16_to_ui32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + uint32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (sign || (exp == 0x1F)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (uint32_t) (frac | 0x0400)<>10; +} diff --git a/src/cpu/softfloat3e/f16_to_ui64.c b/src/cpu/softfloat3e/f16_to_ui64.c new file mode 100644 index 0000000000..351edb32ce --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_ui64.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f16_to_ui64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int8_t exp; + uint16_t frac; + uint32_t sig32; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + exp = expF16UI(a); + frac = fracF16UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x1F) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + frac ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig32 = frac; + if (exp) { + sig32 |= 0x0400; + shiftDist = exp - 0x19; + if ((0 <= shiftDist) && ! sign) { + return sig32<>12, (uint64_t) sig32<<52, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c new file mode 100644 index 0000000000..d80d6e8f5d --- /dev/null +++ b/src/cpu/softfloat3e/f16_to_ui64_r_minMag.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f16_to_ui64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status) +{ + int8_t exp; + uint16_t frac; + int8_t shiftDist; + bool sign; + uint32_t alignedSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF16UI(a); + frac = fracF16UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && frac) frac = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = exp - 0x0F; + if (shiftDist < 0) { + if (exact && (exp | frac)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF16UI(a); + if (sign || (exp == 0x1F)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x1F) && frac + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + alignedSig = (uint32_t) (frac | 0x0400)<>10; +} diff --git a/src/cpu/softfloat/f2xm1.cc b/src/cpu/softfloat3e/f2xm1.cc similarity index 77% rename from src/cpu/softfloat/f2xm1.cc rename to src/cpu/softfloat3e/f2xm1.cc index ed4af1d125..16daec1d36 100644 --- a/src/cpu/softfloat/f2xm1.cc +++ b/src/cpu/softfloat3e/f2xm1.cc @@ -25,12 +25,15 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "specialize.h" + +#include "fpu_trans.h" +#include "softfloat-helpers.h" static const floatx80 floatx80_negone = packFloatx80(1, 0x3fff, BX_CONST64(0x8000000000000000)); static const floatx80 floatx80_neghalf = packFloatx80(1, 0x3ffe, BX_CONST64(0x8000000000000000)); -static const float128 float128_ln2 = +static const float128_t float128_ln2 = packFloat128(BX_CONST64(0x3ffe62e42fefa39e), BX_CONST64(0xf35793c7673007e6)); #ifdef BETTER_THAN_PENTIUM @@ -47,7 +50,7 @@ static const float128 float128_ln2 = #define EXP_ARR_SIZE 15 -static float128 exp_arr[EXP_ARR_SIZE] = +static float128_t exp_arr[EXP_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */ @@ -66,10 +69,10 @@ static float128 exp_arr[EXP_ARR_SIZE] = PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */ }; -extern float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status); +extern float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status); /* required -1 < x < 1 */ -static float128 poly_exp(float128 x, struct float_status_t *status) +static float128_t poly_exp(float128_t x, struct softfloat_status_t *status) { /* // 2 3 4 5 6 7 8 9 @@ -92,8 +95,8 @@ static float128 poly_exp(float128 x, struct float_status_t *status) // e - 1 ~ x * [ p(x) + x * q(x) ] // */ - float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE, status); - return float128_mul(t, x, status); + float128_t t = EvalPoly(x, (const float128_t*) exp_arr, EXP_ARR_SIZE, status); + return f128_mul(t, x, status); } // ================================================= @@ -114,49 +117,51 @@ static float128 poly_exp(float128 x, struct float_status_t *status) // e = 1 + --- + --- + --- + --- + --- + ... + --- + ... // 1! 2! 3! 4! 5! n! // - -floatx80 f2xm1(floatx80 a, struct float_status_t *status) +floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit64u zSig0, zSig1, zSig2; + static const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + uint64_t zSig0, zSig1, zSig2; + struct exp32_sig64 normExpSig; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) - { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaNOne(a, status); + if (aSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, 0, 0, status); return (aSign) ? floatx80_negone : a; } - if (aExp == 0) { - if (aSig == 0) return a; - float_raise(status, float_flag_denormal | float_flag_inexact); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + if (! aExp) { + if (! aSig) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal | softfloat_flag_inexact); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; tiny_argument: mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { + if (0 < (int64_t) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --aExp; } - return - roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1, status); + return softfloat_roundPackToExtF80(aSign, aExp, zSig0, zSig1, 80, status); } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(status, softfloat_flag_inexact); if (aExp < 0x3FFF) { @@ -167,14 +172,14 @@ floatx80 f2xm1(floatx80 a, struct float_status_t *status) /* using float128 for approximation */ /* ******************************** */ - float128 x = floatx80_to_float128(a, status); - x = float128_mul(x, float128_ln2, status); + float128_t x = extF80_to_f128(a, status); + x = f128_mul(x, float128_ln2, status); x = poly_exp(x, status); - return float128_to_floatx80(x, status); + return f128_to_extF80(x, status); } else { - if (a.exp == 0xBFFF && ! (aSig<<1)) + if (a.signExp == 0xBFFF && ! (aSig<<1)) return floatx80_neghalf; return a; diff --git a/src/cpu/softfloat3e/f32_addsub.c b/src/cpu/softfloat3e/f32_addsub.c new file mode 100644 index 0000000000..0b12d0e76a --- /dev/null +++ b/src/cpu/softfloat3e/f32_addsub.c @@ -0,0 +1,60 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +extern float32 softfloat_addMagsF32(uint32_t, uint32_t, struct softfloat_status_t *); +extern float32 softfloat_subMagsF32(uint32_t, uint32_t, struct softfloat_status_t *); + +float32 f32_add(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (signF32UI((uint32_t) a ^ (uint32_t) b)) { + return softfloat_subMagsF32(a, b, status); + } else { + return softfloat_addMagsF32(a, b, status); + } +} + +float32 f32_sub(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (signF32UI((uint32_t) a ^ (uint32_t) b)) { + return softfloat_addMagsF32(a, b, status); + } else { + return softfloat_subMagsF32(a, b, status); + } +} diff --git a/src/cpu/softfloat3e/f32_class.c b/src/cpu/softfloat3e/f32_class.c new file mode 100644 index 0000000000..84c337d0e8 --- /dev/null +++ b/src/cpu/softfloat3e/f32_class.c @@ -0,0 +1,64 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t f32_class(float32 a) +{ + bool signA; + int16_t expA; + uint32_t sigA; + + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & 0x00400000) ? softfloat_QNaN : softfloat_SNaN; + } + + if (expA == 0) { + if (sigA == 0) return softfloat_zero; + return softfloat_denormal; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/f32_compare.c b/src/cpu/softfloat3e/f32_compare.c new file mode 100644 index 0000000000..6c8ecfaaec --- /dev/null +++ b/src/cpu/softfloat3e/f32_compare.c @@ -0,0 +1,92 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int f32_compare(float32 a, float32 b, bool quiet, struct softfloat_status_t *status) +{ + softfloat_class_t aClass; + softfloat_class_t bClass; + bool signA; + bool signB; + + aClass = f32_class(a); + bClass = f32_class(b); + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + a = a & 0x80000000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if (bClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + b = b & 0x80000000; + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if ((a == b) || ((uint32_t) ((a | b)<<1) == 0)) return softfloat_relation_equal; + + signA = signF32UI(a); + signB = signF32UI(b); + if (signA != signB) + return (signA) ? softfloat_relation_less : softfloat_relation_greater; + + if (signA ^ (a < b)) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/f32_div.c b/src/cpu/softfloat3e/f32_div.c new file mode 100644 index 0000000000..a9ccfcfd4a --- /dev/null +++ b/src/cpu/softfloat3e/f32_div.c @@ -0,0 +1,146 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +#define SOFTFLOAT_FAST_DIV64TO32 + +float32 f32_div(float32 a, float32 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signZ; + struct exp16_sig32 normExpSig; + int16_t expZ; +#ifdef SOFTFLOAT_FAST_DIV64TO32 + uint64_t sig64A; + uint32_t sigZ; +#endif + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA) goto propagateNaN; + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + goto invalid; + } + if (sigB && !expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infinity; + } + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) { + if (! (expA | sigA)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! sigA) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x7E; + sigA |= 0x00800000; + sigB |= 0x00800000; +#ifdef SOFTFLOAT_FAST_DIV64TO32 + if (sigA < sigB) { + --expZ; + sig64A = (uint64_t) sigA<<31; + } else { + sig64A = (uint64_t) sigA<<30; + } + sigZ = sig64A / sigB; + if (! (sigZ & 0x3F)) sigZ |= ((uint64_t) sigB * sigZ != sig64A); +#endif + return softfloat_roundPackToF32(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF32UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + return packToF32UI(signZ, 0xFF, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF32UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f32_frc.c b/src/cpu/softfloat3e/f32_frc.c new file mode 100644 index 0000000000..fc1b024603 --- /dev/null +++ b/src/cpu/softfloat3e/f32_frc.c @@ -0,0 +1,101 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the fractional portion of single-precision floating-point value `a', +| and returns the result as a single-precision floating-point value. The +| fractional results are precise. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_frc(float32 a, struct softfloat_status_t *status) +{ + int roundingMode = softfloat_getRoundingMode(status); + + bool signA; + int16_t expA; + uint32_t sigA; + uint32_t lastBitMask; + uint32_t roundBitsMask; + + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA) return softfloat_propagateNaNF32UI(a, 0, status); + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + + if (expA >= 0x96) { + return packToF32UI(roundingMode == softfloat_round_down, 0, 0); + } + + if (expA < 0x7F) { + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF32UI(roundingMode == softfloat_round_down, 0, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) + softfloat_raiseFlags(status, softfloat_flag_underflow); + + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(signA, 0, 0); + } + } + return a; + } + + lastBitMask = 1 << (0x96 - expA); + roundBitsMask = lastBitMask - 1; + + sigA &= roundBitsMask; + sigA <<= 7; + expA--; + + if (! sigA) + return packToF32UI(roundingMode == softfloat_round_down, 0, 0); + + return softfloat_normRoundPackToF32(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f32_getExp.c b/src/cpu/softfloat3e/f32_getExp.c new file mode 100644 index 0000000000..66b00ac7c5 --- /dev/null +++ b/src/cpu/softfloat3e/f32_getExp.c @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of single-precision floating-point value 'a', +| and returns the result as a single-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_getExp(float32 a, struct softfloat_status_t *status) +{ + int16_t expA; + uint32_t sigA; + struct exp16_sig32 normExpSig; + + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA) return softfloat_propagateNaNF32UI(a, 0, status); + return packToF32UI(0, 0xFF, 0); + } + + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF32UI(1, 0xFF, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + } + + return i32_to_f32((int32_t)(expA) - 0x7F, status); +} diff --git a/src/cpu/softfloat3e/f32_getMant.c b/src/cpu/softfloat3e/f32_getMant.c new file mode 100644 index 0000000000..9dfa58a632 --- /dev/null +++ b/src/cpu/softfloat3e/f32_getMant.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of single-precision floating-point value 'a' and +| returns the result as a single-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_getMant(float32 a, struct softfloat_status_t *status, int sign_ctrl, int interv) +{ + bool signA; + int16_t expA; + uint32_t sigA; + struct exp16_sig32 normExpSig; + + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + + if (expA == 0xFF) { + if (sigA) return softfloat_propagateNaNF32UI(a, 0, status); + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + } + return packToF32UI(~sign_ctrl & signA, 0x7F, 0); + } + + if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) { + return packToF32UI(~sign_ctrl & signA, 0x7F, 0); + } + + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + } + + if (! expA) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + sigA &= 0x7FFFFF; + } + + switch(interv) { + case 0x0: // interval [1,2) + expA = 0x7F; + break; + case 0x1: // interval [1/2,2) + expA -= 0x7F; + expA = 0x7F - (expA & 0x1); + break; + case 0x2: // interval [1/2,1) + expA = 0x7E; + break; + case 0x3: // interval [3/4,3/2) + expA = 0x7F - ((sigA >> 22) & 0x1); + break; + } + + return packToF32UI(~sign_ctrl & signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/f32_minmax.c b/src/cpu/softfloat3e/f32_minmax.c new file mode 100644 index 0000000000..e36c297ae7 --- /dev/null +++ b/src/cpu/softfloat3e/f32_minmax.c @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float32 f32_min(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f32_denormal_to_zero(a); + b = f32_denormal_to_zero(b); + } + + return (f32_compare_normal(a, b, status) == softfloat_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two single precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float32 f32_max(float32 a, float32 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f32_denormal_to_zero(a); + b = f32_denormal_to_zero(b); + } + + return (f32_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b; +} diff --git a/src/cpu/softfloat3e/f32_mul.c b/src/cpu/softfloat3e/f32_mul.c new file mode 100644 index 0000000000..db96e0db7a --- /dev/null +++ b/src/cpu/softfloat3e/f32_mul.c @@ -0,0 +1,137 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_mul(float32 a, float32 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signZ; + uint32_t magBits; + struct exp16_sig32 normExpSig; + int16_t expZ; + uint32_t sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA || ((expB == 0xFF) && sigB)) goto propagateNaN; + magBits = expB | sigB; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + magBits = expA | sigA; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) { + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x7F; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<8; + sigZ = softfloat_shortShiftRightJam64((uint64_t) sigA * sigB, 32); + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF32(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF32UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF32UI; + } else { + uiZ = packToF32UI(signZ, 0xFF, 0); + } + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF32UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f32_mulAdd.c b/src/cpu/softfloat3e/f32_mulAdd.c new file mode 100644 index 0000000000..101b20f18b --- /dev/null +++ b/src/cpu/softfloat3e/f32_mulAdd.c @@ -0,0 +1,233 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" +#include "specialize.h" + +float32 f32_mulAdd(float32 a, float32 b, float32 c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool signC; + int16_t expC; + uint32_t sigC; + bool signProd; + uint32_t magBits, uiA, uiB, uiC, uiZ; + struct exp16_sig32 normExpSig; + int16_t expProd; + uint64_t sigProd; + bool signZ; + int16_t expZ; + uint32_t sigZ; + int16_t expDiff; + uint64_t sig64Z, sig64C; + int8_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(uiA); + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + signB = signF32UI(uiB); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + signC = signF32UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF32UI(uiC); + sigC = fracF32UI(uiC); + signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0xFF) && sigA; + bool bisNaN = (expB == 0xFF) && sigB; + bool cisNaN = (expC == 0xFF) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF32UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF32UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0xFF) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0xFF) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF32UI(signC, 0xFF, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expProd = expA + expB - 0x7E; + sigA = (sigA | 0x00800000)<<7; + sigB = (sigB | 0x00800000)<<7; + sigProd = (uint64_t) sigA * sigB; + if (sigProd < UINT64_C(0x2000000000000000)) { + --expProd; + sigProd <<= 1; + } + signZ = signProd; + if (! expC) { + if (! sigC) { + expZ = expProd - 1; + sigZ = softfloat_shortShiftRightJam64(sigProd, 31); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | 0x00800000)<<6; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expProd - expC; + if (signProd == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + expZ = expC; + sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff); + } else { + expZ = expProd; + sig64Z = sigProd + softfloat_shiftRightJam64((uint64_t) sigC<<32, expDiff); + sigZ = softfloat_shortShiftRightJam64(sig64Z, 32); + } + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig64C = (uint64_t) sigC<<32; + if (expDiff < 0) { + signZ = signC; + expZ = expC; + sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff); + } else if (! expDiff) { + expZ = expProd; + sig64Z = sigProd - sig64C; + if (! sig64Z) goto completeCancellation; + if (sig64Z & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + sig64Z = -sig64Z; + } + } else { + expZ = expProd; + sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff); + } + shiftDist = softfloat_countLeadingZeros64(sig64Z) - 1; + expZ -= shiftDist; + shiftDist -= 32; + if (shiftDist < 0) { + sigZ = softfloat_shortShiftRightJam64(sig64Z, -shiftDist); + } else { + sigZ = (uint32_t) sig64Z< +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_range(float32 a, float32 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + bool aIsNaN, bIsNaN; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_isSigNaNF32UI(a)) { + return softfloat_propagateNaNF32UI(a, 0, status); + } + if (softfloat_isSigNaNF32UI(b)) { + return softfloat_propagateNaNF32UI(b, 0, status); + } + + aIsNaN = isNaNF32UI(a); + bIsNaN = isNaNF32UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA && sigA) { + if (softfloat_denormalsAreZeros(status)) { + a = packToF32UI(signA, 0, 0); + } + else if (! bIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + + if (! expB && sigB) { + if (softfloat_denormalsAreZeros(status)) { + b = packToF32UI(signB, 0, 0); + } + else if (! aIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (bIsNaN) { + z = a; + } + else if (aIsNaN) { + z = b; + } + else if (signA != signB && ! is_abs) { + if (! is_max) { + z = signA ? a : b; + } else { + z = signA ? b : a; + } + } else { + float32 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a = tmp_a & ~0x80000000; // clear the sign bit + tmp_b = tmp_b & ~0x80000000; + signA = 0; + } + if (! is_max) { + z = (signA ^ (tmp_a < tmp_b)) ? a : b; + } else { + z = (signA ^ (tmp_a < tmp_b)) ? b : a; + } + } + + switch(sign_ctrl) { + case 0: + z = (z & ~0x80000000) | (a & 0x80000000); // keep sign of a + break; + case 1: + break; // preserve sign of compare result + case 2: + z = z & ~0x80000000; // zero out the sign bit + break; + case 3: + z = z | 0x80000000; // set the sign bit + break; + } + + return z; +} diff --git a/src/cpu/softfloat3e/f32_roundToInt.c b/src/cpu/softfloat3e/f32_roundToInt.c new file mode 100644 index 0000000000..7791fbbf41 --- /dev/null +++ b/src/cpu/softfloat3e/f32_roundToInt.c @@ -0,0 +1,112 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_roundToInt(float32 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + int32_t frac; + uint32_t uiZ, lastBitMask, roundBitsMask; + bool sign; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + scale &= 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + frac = fracF32UI(a); + sign = signF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x96 <= (exp + scale)) { + if ((exp == 0xFF) && frac) { + return softfloat_propagateNaNF32UI(a, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!exp) { + frac = 0; + a = packToF32UI(sign, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((exp + scale) <= 0x7E) { + if (!(exp | frac)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ = packToF32UI(sign, 0, 0); + switch (roundingMode) { + case softfloat_round_near_even: + if (!frac) break; + case softfloat_round_near_maxMag: + if ((exp + scale) == 0x7E) uiZ |= packToF32UI(0, 0x7F - scale, 0); + break; + case softfloat_round_min: + if (uiZ) uiZ = packToF32UI(1, 0x7F - scale, 0); + break; + case softfloat_round_max: + if (!uiZ) uiZ = packToF32UI(0, 0x7F - scale, 0); + break; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = a; + lastBitMask = (uint32_t) 1<<(0x96 - exp - scale); + roundBitsMask = lastBitMask - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ += lastBitMask>>1; + if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask; + } else if (roundingMode == (signF32UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if (uiZ != a) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f32_scalef.c b/src/cpu/softfloat3e/f32_scalef.c new file mode 100644 index 0000000000..320baff30a --- /dev/null +++ b/src/cpu/softfloat3e/f32_scalef.c @@ -0,0 +1,155 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Return the result of a floating point scale of the single-precision floating +| point value `a' by multiplying it by 2 power of the single-precision +| floating point value 'b' converted to integral value. If the result cannot +| be represented in single precision, then the proper overflow response (for +| positive scaling operand), or the proper underflow response (for negative +| scaling operand) is issued. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float32 f32_scalef(float32 a, float32 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + bool signB; + int16_t expB; + uint32_t sigB; + int shiftCount; + int scale = 0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + signB = signF32UI(b); + expB = expF32UI(b); + sigB = fracF32UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB == 0xFF) { + if (sigB) return softfloat_propagateNaNF32UI(a, b, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA) { + int aIsSignalingNaN = (sigA & 0x00400000) == 0; + if (aIsSignalingNaN || expB != 0xFF || sigB) + return softfloat_propagateNaNF32UI(a, b, status); + + return signB ? 0 : packToF32UI(0, 0xFF, 0); + } + + if (expB == 0xFF && signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (expB == 0xFF && ! signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + return packToF32UI(signA, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((expB | sigB) == 0) return a; + + if (expB == 0xFF) { + if (signB) return packToF32UI(signA, 0, 0); + return packToF32UI(signA, 0xFF, 0); + } + + if (expB >= 0x8E) { + // handle obvious overflow/underflow result + return softfloat_roundPackToF32(signA, signB ? -0x7F : 0xFF, sigA, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB <= 0x7E) { + if (! expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + scale = -signB; + } + else { + shiftCount = expB - 0x9E; + sigB = (sigB | 0x800000)<<8; + scale = sigB>>(-shiftCount); + + if (signB) { + if ((uint32_t) (sigB<<(shiftCount & 31))) scale++; + scale = -scale; + } + + if (scale > 0x200) scale = 0x200; + if (scale < -0x200) scale = -0x200; + } + + if (expA != 0) { + sigA |= 0x00800000; + } else { + expA++; + } + + expA += scale - 1; + sigA <<= 7; + return softfloat_normRoundPackToF32(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f32_sqrt.c b/src/cpu/softfloat3e/f32_sqrt.c new file mode 100644 index 0000000000..fc2ef8f761 --- /dev/null +++ b/src/cpu/softfloat3e/f32_sqrt.c @@ -0,0 +1,117 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f32_sqrt(float32 a, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint32_t sigA; + struct exp16_sig32 normExpSig; + int16_t expZ; + uint32_t sigZ, shiftedSigZ; + uint32_t negRem; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF32UI(a); + expA = expF32UI(a); + sigA = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA) { + return softfloat_propagateNaNF32UI(a, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + a = packToF32UI(signA, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if (! (expA | sigA)) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x7F)>>1) + 0x7E; + expA &= 1; + sigA = (sigA | 0x00800000)<<8; + sigZ = + ((uint64_t) sigA * softfloat_approxRecipSqrt32_1(expA, sigA))>>32; + if (expA) sigZ >>= 1; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigZ += 2; + if ((sigZ & 0x3F) < 2) { + shiftedSigZ = sigZ>>2; + negRem = shiftedSigZ * shiftedSigZ; + sigZ &= ~3; + if (negRem & 0x80000000) { + sigZ |= 1; + } else { + if (negRem) --sigZ; + } + } + return softfloat_roundPackToF32(0, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; +} diff --git a/src/cpu/softfloat3e/f32_to_extF80.cc b/src/cpu/softfloat3e/f32_to_extF80.cc new file mode 100644 index 0000000000..73b8bedfdd --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_extF80.cc @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f32_to_extF80(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp16_sig32 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(frac); + exp = normExpSig.exp; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = packToExtF80UI64(sign, exp + 0x3F80); + uiZ0 = (uint64_t) (frac | 0x00800000)<<40; + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/f32_to_f128.cc b/src/cpu/softfloat3e/f32_to_f128.cc new file mode 100644 index 0000000000..6d3fafec29 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_f128.cc @@ -0,0 +1,86 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f32_to_f128(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + struct exp16_sig32 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF128UI(&commonNaN); + } else { + uiZ.v64 = packToF128UI64(sign, 0x7FFF, 0); + uiZ.v0 = 0; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + uiZ.v64 = packToF128UI64(sign, 0, 0); + uiZ.v0 = 0; + return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ.v64 = packToF128UI64(sign, exp + 0x3F80, (uint64_t) frac<<25); + uiZ.v0 = 0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f32_to_f16.c b/src/cpu/softfloat3e/f32_to_f16.c new file mode 100644 index 0000000000..9253a958a5 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_f16.c @@ -0,0 +1,82 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f32_to_f16(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + uint16_t uiZ, frac16; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF16UI(&commonNaN); + } else { + uiZ = packToF16UI(sign, 0x1F, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (!exp && frac) { + if (softfloat_denormalsAreZeros(status)) + return packToF16UI(sign, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac16 = frac>>9 | ((frac & 0x1FF) != 0); + if (! (exp | frac16)) { + return packToF16UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF16(sign, exp - 0x71, frac16 | 0x4000, status); +} diff --git a/src/cpu/softfloat3e/f32_to_f64.c b/src/cpu/softfloat3e/f32_to_f64.c new file mode 100644 index 0000000000..28ebb61b6c --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_f64.c @@ -0,0 +1,81 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f32_to_f64(float32 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t frac; + struct commonNaN commonNaN; + uint64_t uiZ; + struct exp16_sig32 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + frac = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0xFF) { + if (frac) { + softfloat_f32UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF64UI(&commonNaN); + } else { + uiZ = packToF64UI(sign, 0x7FF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac || softfloat_denormalsAreZeros(status)) { + return packToF64UI(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF32Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF64UI(sign, exp + 0x380, (uint64_t) frac<<29); +} diff --git a/src/cpu/softfloat3e/f32_to_i32.c b/src/cpu/softfloat3e/f32_to_i32.c new file mode 100644 index 0000000000..2b3df52a3c --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_i32.c @@ -0,0 +1,78 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f32_to_i32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + uint64_t sig64; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0xFF) && sig) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + else if (softfloat_denormalsAreZeros(status)) sig = 0; + sig64 = (uint64_t) sig<<32; + shiftDist = 0xAA - exp; + if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + return softfloat_roundToI32(sign, sig64, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_i32_r_minMag.c b/src/cpu/softfloat3e/f32_to_i32_r_minMag.c new file mode 100644 index 0000000000..abe782d3b0 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_i32_r_minMag.c @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f32_to_i32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + int32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x9E - exp; + if (32 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (shiftDist <= 0) { + if (a == packToF32UI(1, 0x9E, 0)) return -0x7FFFFFFF - 1; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = (sig | 0x00800000)<<8; + absZ = sig>>shiftDist; + if (exact && ((uint32_t) absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f32_to_i64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + int16_t shiftDist; + uint64_t sig64, extra; + struct uint64_extra sig64Extra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (shiftDist < 0) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + sig64 = (uint64_t) sig<<40; + extra = 0; + if (shiftDist) { + sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, shiftDist); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return softfloat_roundToI64(sign, sig64, extra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_i64_r_minMag.c b/src/cpu/softfloat3e/f32_to_i64_r_minMag.c new file mode 100644 index 0000000000..2ccabd09de --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_i64_r_minMag.c @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f32_to_i64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + uint64_t sig64; + int64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (shiftDist <= 0) { + if (a == packToF32UI(1, 0xBE, 0)) { + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= 0x00800000; + sig64 = (uint64_t) sig<<40; + absZ = sig64>>shiftDist; + shiftDist = 40 - shiftDist; + if (exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return sign ? -absZ : absZ; +} diff --git a/src/cpu/softfloat3e/f32_to_ui32.c b/src/cpu/softfloat3e/f32_to_ui32.c new file mode 100644 index 0000000000..5a8d574142 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_ui32.c @@ -0,0 +1,80 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f32_to_ui32(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + uint64_t sig64; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0xFF) && sig) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + else if (softfloat_denormalsAreZeros(status)) sig = 0; + sig64 = (uint64_t) sig<<32; + shiftDist = 0xAA - exp; + if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist); + return softfloat_roundToUI32(sign, sig64, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c b/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c new file mode 100644 index 0000000000..4b37708b04 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_ui32_r_minMag.c @@ -0,0 +1,83 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f32_to_ui32_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x9E - exp; + if (32 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (sign || (shiftDist < 0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig = (sig | 0x00800000)<<8; + z = sig>>shiftDist; + if (exact && (z< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f32_to_ui64(float32 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint32_t sig; + int16_t shiftDist; + uint64_t sig64, extra; + struct uint64_extra sig64Extra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + exp = expF32UI(a); + sig = fracF32UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (shiftDist < 0) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= 0x00800000; + else if (softfloat_denormalsAreZeros(status)) sig = 0; + sig64 = (uint64_t) sig<<40; + extra = 0; + if (shiftDist) { + sig64Extra = softfloat_shiftRightJam64Extra(sig64, 0, shiftDist); + sig64 = sig64Extra.v; + extra = sig64Extra.extra; + } + return softfloat_roundToUI64(sign, sig64, extra, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c new file mode 100644 index 0000000000..111c50e7f2 --- /dev/null +++ b/src/cpu/softfloat3e/f32_to_ui64_r_minMag.c @@ -0,0 +1,84 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f32_to_ui64_r_minMag(float32 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint32_t sig; + int16_t shiftDist; + bool sign; + uint64_t sig64, z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF32UI(a); + sig = fracF32UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0xBE - exp; + if (64 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF32UI(a); + if (sign || (shiftDist < 0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0xFF) && sig + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= 0x00800000; + sig64 = (uint64_t) sig<<40; + z = sig64>>shiftDist; + shiftDist = 40 - shiftDist; + if (exact && (shiftDist < 0) && (uint32_t) (sig<<(shiftDist & 31))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return z; +} diff --git a/src/cpu/softfloat3e/f64_addsub.c b/src/cpu/softfloat3e/f64_addsub.c new file mode 100644 index 0000000000..6c5acb4f77 --- /dev/null +++ b/src/cpu/softfloat3e/f64_addsub.c @@ -0,0 +1,70 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +extern float64 softfloat_addMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); +extern float64 softfloat_subMagsF64(uint64_t, uint64_t, bool, struct softfloat_status_t *); + +float64 f64_add(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + bool signB; + + signA = signF64UI(a); + signB = signF64UI(b); + if (signA == signB) { + return softfloat_addMagsF64(a, b, signA, status); + } else { + return softfloat_subMagsF64(a, b, signA, status); + } +} + +float64 f64_sub(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + bool signB; + + signA = signF64UI(a); + signB = signF64UI(b); + if (signA == signB) { + return softfloat_subMagsF64(a, b, signA, status); + } else { + return softfloat_addMagsF64(a, b, signA, status); + } +} diff --git a/src/cpu/softfloat3e/f64_class.c b/src/cpu/softfloat3e/f64_class.c new file mode 100644 index 0000000000..1d44a63518 --- /dev/null +++ b/src/cpu/softfloat3e/f64_class.c @@ -0,0 +1,64 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +softfloat_class_t f64_class(float64 a) +{ + bool signA; + int16_t expA; + uint64_t sigA; + + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA == 0) + return (signA) ? softfloat_negative_inf : softfloat_positive_inf; + + return (sigA & UINT64_C(0x0008000000000000)) ? softfloat_QNaN : softfloat_SNaN; + } + + if (expA == 0) { + if (sigA == 0) return softfloat_zero; + return softfloat_denormal; + } + + return softfloat_normalized; +} diff --git a/src/cpu/softfloat3e/f64_compare.c b/src/cpu/softfloat3e/f64_compare.c new file mode 100644 index 0000000000..aed2507682 --- /dev/null +++ b/src/cpu/softfloat3e/f64_compare.c @@ -0,0 +1,92 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers. Returns +| 'float_relation_equal' if the operands are equal, 'float_relation_less' if +| the value 'a' is less than the corresponding value `b', +| 'float_relation_greater' if the value 'a' is greater than the corresponding +| value `b', or 'float_relation_unordered' otherwise. +*----------------------------------------------------------------------------*/ + +int f64_compare(float64 a, float64 b, bool quiet, struct softfloat_status_t *status) +{ + softfloat_class_t aClass; + softfloat_class_t bClass; + bool signA; + bool signB; + + aClass = f64_class(a); + bClass = f64_class(b); + + if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) { + if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid); + return softfloat_relation_unordered; + } + + if (aClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + a = a & UINT64_C(0x8000000000000000); + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if (bClass == softfloat_denormal) { + if (softfloat_denormalsAreZeros(status)) + b = b & UINT64_C(0x8000000000000000); + else + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + + if ((a == b) || ((uint64_t) ((a | b)<<1) == 0)) return softfloat_relation_equal; + + signA = signF64UI(a); + signB = signF64UI(b); + if (signA != signB) + return (signA) ? softfloat_relation_less : softfloat_relation_greater; + + if (signA ^ (a < b)) return softfloat_relation_less; + return softfloat_relation_greater; +} diff --git a/src/cpu/softfloat3e/f64_div.c b/src/cpu/softfloat3e/f64_div.c new file mode 100644 index 0000000000..89f74f1b10 --- /dev/null +++ b/src/cpu/softfloat3e/f64_div.c @@ -0,0 +1,165 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_div(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signZ; + struct exp16_sig64 normExpSig; + int16_t expZ; + uint32_t recip32, sig32Z, doubleTerm; + uint64_t rem; + uint32_t q; + uint64_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA) goto propagateNaN; + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + goto invalid; + } + if (sigB && !expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infinity; + } + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) { + if (! (expA | sigA)) goto invalid; + softfloat_raiseFlags(status, softfloat_flag_infinite); + goto infinity; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + if (! expA) { + if (! sigA) goto zero; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA - expB + 0x3FE; + sigA |= UINT64_C(0x0010000000000000); + sigB |= UINT64_C(0x0010000000000000); + if (sigA < sigB) { + --expZ; + sigA <<= 11; + } else { + sigA <<= 10; + } + sigB <<= 11; + recip32 = softfloat_approxRecip32_1(sigB>>32) - 2; + sig32Z = ((uint32_t) (sigA>>32) * (uint64_t) recip32)>>32; + doubleTerm = sig32Z<<1; + rem = + ((sigA - (uint64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint64_t) doubleTerm * ((uint32_t) sigB>>4); + q = (((uint32_t) (rem>>32) * (uint64_t) recip32)>>32) + 4; + sigZ = ((uint64_t) sig32Z<<32) + ((uint64_t) q<<4); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((sigZ & 0x1FF) < 4<<4) { + q &= ~7; + sigZ &= ~(uint64_t) 0x7F; + doubleTerm = q<<1; + rem = + ((rem - (uint64_t) doubleTerm * (uint32_t) (sigB>>32))<<28) + - (uint64_t) doubleTerm * ((uint32_t) sigB>>4); + if (rem & UINT64_C(0x8000000000000000)) { + sigZ -= 1<<7; + } else { + if (rem) sigZ |= 1; + } + } + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF64UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infinity: + return packToF64UI(signZ, 0x7FF, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF64UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f64_frc.c b/src/cpu/softfloat3e/f64_frc.c new file mode 100644 index 0000000000..46c21ac4f8 --- /dev/null +++ b/src/cpu/softfloat3e/f64_frc.c @@ -0,0 +1,101 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the fractional portion of double-precision floating-point value `a', +| and returns the result as a double-precision floating-point value. The +| fractional results are precise. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_frc(float64 a, struct softfloat_status_t *status) +{ + int roundingMode = softfloat_getRoundingMode(status); + + bool signA; + int16_t expA; + uint64_t sigA; + uint64_t lastBitMask; + uint64_t roundBitsMask; + + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA) return softfloat_propagateNaNF64UI(a, 0, status); + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + + if (expA >= 0x433) { + return packToF64UI(roundingMode == softfloat_round_down, 0, 0); + } + + if (expA < 0x3FF) { + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF64UI(roundingMode == softfloat_round_down, 0, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) + softfloat_raiseFlags(status, softfloat_flag_underflow); + + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signA, 0, 0); + } + } + return a; + } + + lastBitMask = UINT64_C(1) << (0x433 - expA); + roundBitsMask = lastBitMask - 1; + + sigA &= roundBitsMask; + sigA <<= 10; + expA--; + + if (! sigA) + return packToF64UI(roundingMode == softfloat_round_down, 0, 0); + + return softfloat_normRoundPackToF64(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f64_getExp.c b/src/cpu/softfloat3e/f64_getExp.c new file mode 100644 index 0000000000..b76cc996d5 --- /dev/null +++ b/src/cpu/softfloat3e/f64_getExp.c @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the exponent portion of double-precision floating-point value 'a', +| and returns the result as a double-precision floating-point value +| representing unbiased integer exponent. The operation is performed according +| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_getExp(float64 a, struct softfloat_status_t *status) +{ + int16_t expA; + uint64_t sigA; + struct exp16_sig64 normExpSig; + + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA) return softfloat_propagateNaNF64UI(a, 0, status); + return packToF64UI(0, 0x7FF, 0); + } + + if (! expA) { + if (! sigA || softfloat_denormalsAreZeros(status)) + return packToF64UI(1, 0x7FF, 0); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + } + + return i32_to_f64((int32_t)(expA) - 0x3FF); +} diff --git a/src/cpu/softfloat3e/f64_getMant.c b/src/cpu/softfloat3e/f64_getMant.c new file mode 100644 index 0000000000..84077e3148 --- /dev/null +++ b/src/cpu/softfloat3e/f64_getMant.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Extracts the mantissa of double-precision floating-point value 'a' and +| returns the result as a double-precision floating-point after applying +| the mantissa interval normalization and sign control. The operation is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_getMant(float64 a, struct softfloat_status_t *status, int sign_ctrl, int interv) +{ + bool signA; + int16_t expA; + uint64_t sigA; + struct exp16_sig64 normExpSig; + + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + + if (expA == 0x7FF) { + if (sigA) return softfloat_propagateNaNF64UI(a, 0, status); + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + } + return packToF64UI(~sign_ctrl & signA, 0x3FF, 0); + } + + if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) { + return packToF64UI(~sign_ctrl & signA, 0x3FF, 0); + } + + if (signA) { + if (sign_ctrl & 0x2) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + } + + if (expA == 0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + sigA &= UINT64_C(0xFFFFFFFFFFFFF); + } + + switch(interv) { + case 0x0: // interval [1,2) + expA = 0x3FF; + break; + case 0x1: // interval [1/2,2) + expA -= 0x3FF; + expA = 0x3FF - (expA & 0x1); + break; + case 0x2: // interval [1/2,1) + expA = 0x3FE; + break; + case 0x3: // interval [3/4,3/2) + expA = 0x3FF - ((sigA >> 51) & 0x1); + break; + } + + return packToF64UI(~sign_ctrl & signA, expA, sigA); +} diff --git a/src/cpu/softfloat3e/f64_minmax.c b/src/cpu/softfloat3e/f64_minmax.c new file mode 100644 index 0000000000..3c927410ab --- /dev/null +++ b/src/cpu/softfloat3e/f64_minmax.c @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| smaller of them. +*----------------------------------------------------------------------------*/ + +float64 f64_min(float64 a, float64 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f64_denormal_to_zero(a); + b = f64_denormal_to_zero(b); + } + + return (f64_compare_normal(a, b, status) == softfloat_relation_less) ? a : b; +} + +/*---------------------------------------------------------------------------- +| Compare between two double precision floating point numbers and return the +| larger of them. +*----------------------------------------------------------------------------*/ + +float64 f64_max(float64 a, float64 b, struct softfloat_status_t *status) +{ + if (softfloat_denormalsAreZeros(status)) { + a = f64_denormal_to_zero(a); + b = f64_denormal_to_zero(b); + } + + return (f64_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b; +} diff --git a/src/cpu/softfloat3e/f64_mul.c b/src/cpu/softfloat3e/f64_mul.c new file mode 100644 index 0000000000..c1e98f2b6d --- /dev/null +++ b/src/cpu/softfloat3e/f64_mul.c @@ -0,0 +1,139 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_mul(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signZ; + uint64_t magBits; + struct exp16_sig64 normExpSig; + int16_t expZ; + struct uint128 sig128Z; + uint64_t sigZ, uiZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + signZ = signA ^ signB; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA || ((expB == 0x7FF) && sigB)) goto propagateNaN; + magBits = expB | sigB; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + magBits = expA | sigA; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto infArg; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) { + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + goto zero; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FF; + sigA = (sigA | UINT64_C(0x0010000000000000))<<10; + sigB = (sigB | UINT64_C(0x0010000000000000))<<11; + sig128Z = softfloat_mul64To128(sigA, sigB); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF64UI(a, b, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infArg: + if (! magBits) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF64UI; + } else { + uiZ = packToF64UI(signZ, 0x7FF, 0); + } + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zero: + return packToF64UI(signZ, 0, 0); +} diff --git a/src/cpu/softfloat3e/f64_mulAdd.c b/src/cpu/softfloat3e/f64_mulAdd.c new file mode 100644 index 0000000000..9623b49800 --- /dev/null +++ b/src/cpu/softfloat3e/f64_mulAdd.c @@ -0,0 +1,243 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" +#include "specialize.h" + +float64 f64_mulAdd(float64 a, float64 b, float64 c, uint8_t op, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool signC; + int16_t expC; + uint64_t sigC; + bool signZ; + uint64_t magBits, uiA, uiB, uiC, uiZ; + struct exp16_sig64 normExpSig; + int16_t expZ; + struct uint128 sig128Z; + uint64_t sigZ; + int16_t expDiff; + struct uint128 sig128C; + int8_t shiftDist; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiA = a; + uiB = b; + uiC = c; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(uiA); + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + signB = signF64UI(uiB); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + signC = signF64UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0); + expC = expF64UI(uiC); + sigC = fracF64UI(uiC); + signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + bool aisNaN = (expA == 0x7FF) && sigA; + bool bisNaN = (expB == 0x7FF) && sigB; + bool cisNaN = (expC == 0x7FF) && sigC; + if (aisNaN | bisNaN | cisNaN) { + uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF64UI(uiA, uiB, status) : 0; + return softfloat_propagateNaNF64UI(uiZ, uiC, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + if (!expC) sigC = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + magBits = expB | sigB; + goto infProdArg; + } + if (expB == 0x7FF) { + magBits = expA | sigA; + goto infProdArg; + } + if (expC == 0x7FF) { + if ((sigA && !expA) || (sigB && !expB)) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + return packToF64UI(signC, 0x7FF, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + if (! expB) { + if (! sigB) goto zeroProd; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigB); + expB = normExpSig.exp; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA + expB - 0x3FE; + sigA = (sigA | UINT64_C(0x0010000000000000))<<10; + sigB = (sigB | UINT64_C(0x0010000000000000))<<10; + sig128Z = softfloat_mul64To128(sigA, sigB); + if (sig128Z.v64 < UINT64_C(0x2000000000000000)) { + --expZ; + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0); + } + if (! expC) { + if (! sigC) { + --expZ; + sigZ = sig128Z.v64<<1 | (sig128Z.v0 != 0); + goto roundPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigC); + expC = normExpSig.exp; + sigC = normExpSig.sig; + } + sigC = (sigC | UINT64_C(0x0010000000000000))<<9; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expZ - expC; + if (expDiff < 0) { + expZ = expC; + if ((signZ == signC) || (expDiff < -1)) { + sig128Z.v64 = softfloat_shiftRightJam64(sig128Z.v64, -expDiff); + } else { + sig128Z = softfloat_shortShiftRightJam128(sig128Z.v64, sig128Z.v0, 1); + } + } else if (expDiff) { + sig128C = softfloat_shiftRightJam128(sigC, 0, expDiff); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signZ == signC) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff <= 0) { + sigZ = (sigC + sig128Z.v64) | (sig128Z.v0 != 0); + } else { + sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); + sigZ = sig128Z.v64 | (sig128Z.v0 != 0); + } + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + signZ = signC; + sig128Z = softfloat_sub128(sigC, 0, sig128Z.v64, sig128Z.v0); + } else if (! expDiff) { + sig128Z.v64 = sig128Z.v64 - sigC; + if (! (sig128Z.v64 | sig128Z.v0)) goto completeCancellation; + if (sig128Z.v64 & UINT64_C(0x8000000000000000)) { + signZ = ! signZ; + sig128Z = softfloat_sub128(0, 0, sig128Z.v64, sig128Z.v0); + } + } else { + sig128Z = softfloat_sub128(sig128Z.v64, sig128Z.v0, sig128C.v64, sig128C.v0); + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! sig128Z.v64) { + expZ -= 64; + sig128Z.v64 = sig128Z.v0; + sig128Z.v0 = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig128Z.v64) - 1; + expZ -= shiftDist; + if (shiftDist < 0) { + sigZ = softfloat_shortShiftRightJam64(sig128Z.v64, -shiftDist); + } else { + sig128Z = softfloat_shortShiftLeft128(sig128Z.v64, sig128Z.v0, shiftDist); + sigZ = sig128Z.v64; + } + sigZ |= (sig128Z.v0 != 0); + } + roundPack: + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + infProdArg: + if (magBits) { + uiZ = packToF64UI(signZ, 0x7FF, 0); + if (signZ == signC || expC != 0x7FF) { + if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiZ; + } + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ = defaultNaNF64UI; + return softfloat_propagateNaNF64UI(uiZ, uiC, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + zeroProd: + uiZ = packToF64UI(signC, expC, sigC); + if (!expC && sigC) { + /* Exact zero plus a denormal */ + softfloat_raiseFlags(status, softfloat_flag_denormal); + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signC, 0, 0); + } + } + if (! (expC | sigC) && (signZ != signC)) { + completeCancellation: + uiZ = packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f64_range.c b/src/cpu/softfloat3e/f64_range.c new file mode 100644 index 0000000000..6f01c84cce --- /dev/null +++ b/src/cpu/softfloat3e/f64_range.c @@ -0,0 +1,135 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_range(float64 a, float64 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + bool aIsNaN, bIsNaN; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_isSigNaNF64UI(a)) { + return softfloat_propagateNaNF64UI(a, 0, status); + } + if (softfloat_isSigNaNF64UI(b)) { + return softfloat_propagateNaNF64UI(b, 0, status); + } + + aIsNaN = isNaNF64UI(a); + bIsNaN = isNaNF64UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA && sigA) { + if (softfloat_denormalsAreZeros(status)) { + a = packToF64UI(signA, 0, 0); + } + else if (! bIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + + if (! expB && sigB) { + if (softfloat_denormalsAreZeros(status)) { + b = packToF64UI(signB, 0, 0); + } + else if (! aIsNaN) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (bIsNaN) { + z = a; + } + else if (aIsNaN) { + z = b; + } + else if (signA != signB && ! is_abs) { + if (! is_max) { + z = signA ? a : b; + } else { + z = signA ? b : a; + } + } else { + float64 tmp_a = a, tmp_b = b; + if (is_abs) { + tmp_a = tmp_a & ~UINT64_C(0x8000000000000000); // clear the sign bit + tmp_b = tmp_b & ~UINT64_C(0x8000000000000000); + signA = 0; + } + + if (! is_max) { + z = (signA ^ (tmp_a < tmp_b)) ? a : b; + } else { + z = (signA ^ (tmp_a < tmp_b)) ? b : a; + } + } + + switch(sign_ctrl) { + case 0: + z = (z & ~UINT64_C(0x8000000000000000)) | (a & UINT64_C(0x8000000000000000)); // keep sign of a + break; + case 1: + break; // preserve sign of compare result + case 2: + z = z & ~UINT64_C(0x8000000000000000); // zero out the sign bit + break; + case 3: + z = z | UINT64_C(0x8000000000000000); // set the sign bit + break; + } + + return z; +} diff --git a/src/cpu/softfloat3e/f64_roundToInt.c b/src/cpu/softfloat3e/f64_roundToInt.c new file mode 100644 index 0000000000..3c5f7fb8c2 --- /dev/null +++ b/src/cpu/softfloat3e/f64_roundToInt.c @@ -0,0 +1,112 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_roundToInt(float64 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + int64_t frac; + bool sign; + uint64_t uiZ, lastBitMask, roundBitsMask; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + scale &= 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + frac = fracF64UI(a); + sign = signF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x433 <= (exp + scale)) { + if ((exp == 0x7FF) && frac) { + return softfloat_propagateNaNF64UI(a, 0, status); + } + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!exp) { + frac = 0; + a = packToF64UI(sign, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((exp + scale) <= 0x3FE) { + if (!(exp | frac)) return a; + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + uiZ = packToF64UI(sign, 0, 0); + switch (roundingMode) { + case softfloat_round_near_even: + if (!frac) break; + case softfloat_round_near_maxMag: + if ((exp + scale) == 0x3FE) uiZ |= packToF64UI(0, 0x3FF - scale, 0); + break; + case softfloat_round_min: + if (uiZ) uiZ = packToF64UI(1, 0x3FF - scale, 0); + break; + case softfloat_round_max: + if (!uiZ) uiZ = packToF64UI(0, 0x3FF - scale, 0); + break; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ = a; + lastBitMask = (uint64_t) 1<<(0x433 - exp - scale); + roundBitsMask = lastBitMask - 1; + if (roundingMode == softfloat_round_near_maxMag) { + uiZ += lastBitMask>>1; + } else if (roundingMode == softfloat_round_near_even) { + uiZ += lastBitMask>>1; + if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask; + } else if (roundingMode == (signF64UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + uiZ += roundBitsMask; + } + uiZ &= ~roundBitsMask; + if (uiZ != a) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return uiZ; +} diff --git a/src/cpu/softfloat3e/f64_scalef.c b/src/cpu/softfloat3e/f64_scalef.c new file mode 100644 index 0000000000..7a552ccc3b --- /dev/null +++ b/src/cpu/softfloat3e/f64_scalef.c @@ -0,0 +1,156 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Return the result of a floating point scale of the double-precision floating +| point value `a' by multiplying it by 2 power of the double-precision +| floating point value 'b' converted to integral value. If the result cannot +| be represented in double precision, then the proper overflow response (for +| positive scaling operand), or the proper underflow response (for negative +| scaling operand) is issued. The operation is performed according to the +| IEC/IEEE Standard for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +float64 f64_scalef(float64 a, float64 b, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + bool signB; + int16_t expB; + uint64_t sigB; + int shiftCount; + int scale = 0; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + signB = signF64UI(b); + expB = expF64UI(b); + sigB = fracF64UI(b); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB == 0x7FF) { + if (sigB) return softfloat_propagateNaNF64UI(a, b, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA) { + int aIsSignalingNaN = (sigA & UINT64_C(0x0008000000000000)) == 0; + if (aIsSignalingNaN || expB != 0x7FF || sigB) + return softfloat_propagateNaNF64UI(a, b, status); + + return signB ? 0 : packToF64UI(0, 0x7FF, 0); + } + + if (expB == 0x7FF && signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + + return a; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (expB == 0x7FF && ! signB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + return packToF64UI(signA, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((expB | sigB) == 0) return a; + + if (expB == 0x7FF) { + if (signB) return packToF64UI(signA, 0, 0); + return packToF64UI(signA, 0x7FF, 0); + } + + if (0x40F <= expB) { + // handle obvious overflow/underflow result + return softfloat_roundPackToF64(signA, signB ? -0x3FF : 0x7FF, sigA, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB < 0x3FF) { + if (expB == 0) + softfloat_raiseFlags(status, softfloat_flag_denormal); + scale = -signB; + } + else { + sigB |= UINT64_C(0x0010000000000000); + shiftCount = 0x433 - expB; + uint64_t prev_sigB = sigB; + sigB >>= shiftCount; + scale = (int32_t) sigB; + if (signB) { + if ((sigB< 0x1000) scale = 0x1000; + if (scale < -0x1000) scale = -0x1000; + } + + if (expA != 0) { + sigA |= UINT64_C(0x0010000000000000); + } else { + expA++; + } + + expA += scale - 1; + sigA <<= 10; + return softfloat_normRoundPackToF64(signA, expA, sigA, status); +} diff --git a/src/cpu/softfloat3e/f64_sqrt.c b/src/cpu/softfloat3e/f64_sqrt.c new file mode 100644 index 0000000000..d3ea81af86 --- /dev/null +++ b/src/cpu/softfloat3e/f64_sqrt.c @@ -0,0 +1,130 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 f64_sqrt(float64 a, struct softfloat_status_t *status) +{ + bool signA; + int16_t expA; + uint64_t sigA; + struct exp16_sig64 normExpSig; + int16_t expZ; + uint32_t sig32A, recipSqrt32, sig32Z; + uint64_t rem; + uint32_t q; + uint64_t sigZ, shiftedSigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + signA = signF64UI(a); + expA = expF64UI(a); + sigA = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA) { + return softfloat_propagateNaNF64UI(a, 0, status); + } + if (! signA) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + a = packToF64UI(signA, 0, 0); + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (signA) { + if (! (expA | sigA)) return a; + goto invalid; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) return a; + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(sigA); + expA = normExpSig.exp; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + | (`sig32Z' is guaranteed to be a lower bound on the square root of + | `sig32A', which makes `sig32Z' also a lower bound on the square root of + | `sigA'.) + *------------------------------------------------------------------------*/ + expZ = ((expA - 0x3FF)>>1) + 0x3FE; + expA &= 1; + sigA |= UINT64_C(0x0010000000000000); + sig32A = sigA>>21; + recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A); + sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32; + if (expA) { + sigA <<= 8; + sig32Z >>= 1; + } else { + sigA <<= 9; + } + rem = sigA - (uint64_t) sig32Z * sig32Z; + q = ((uint32_t) (rem>>2) * (uint64_t) recipSqrt32)>>32; + sigZ = ((uint64_t) sig32Z<<32 | 1<<5) + ((uint64_t) q<<3); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((sigZ & 0x1FF) < 0x22) { + sigZ &= ~(uint64_t) 0x3F; + shiftedSigZ = sigZ>>6; + rem = (sigA<<52) - shiftedSigZ * shiftedSigZ; + if (rem & UINT64_C(0x8000000000000000)) { + --sigZ; + } else { + if (rem) sigZ |= 1; + } + } + return softfloat_roundPackToF64(0, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; +} diff --git a/src/cpu/softfloat3e/f64_to_extF80.cc b/src/cpu/softfloat3e/f64_to_extF80.cc new file mode 100644 index 0000000000..88b27f9d3c --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_extF80.cc @@ -0,0 +1,88 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t f64_to_extF80(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + uint16_t uiZ64; + uint64_t uiZ0; + struct exp16_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToExtF80UI(&commonNaN); + uiZ64 = uiZ.v64; + uiZ0 = uiZ.v0; + } else { + uiZ64 = packToExtF80UI64(sign, 0x7FFF); + uiZ0 = UINT64_C(0x8000000000000000); + } + return packToExtF80_twoargs(uiZ64, uiZ0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + return packToExtF80(sign, 0, 0); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(frac); + exp = normExpSig.exp; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + uiZ64 = packToExtF80UI64(sign, exp + 0x3C00); + uiZ0 = (frac | UINT64_C(0x0010000000000000))<<11; + return packToExtF80_twoargs(uiZ64, uiZ0); +} diff --git a/src/cpu/softfloat3e/f64_to_f128.cc b/src/cpu/softfloat3e/f64_to_f128.cc new file mode 100644 index 0000000000..cfae728249 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_f128.cc @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t f64_to_f128(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + struct uint128 uiZ; + struct exp16_sig64 normExpSig; + struct uint128 frac128; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF128UI(&commonNaN); + } else { + uiZ.v64 = packToF128UI64(sign, 0x7FFF, 0); + uiZ.v0 = 0; + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! exp) { + if (! frac) { + uiZ.v64 = packToF128UI64(sign, 0, 0); + uiZ.v0 = 0; + return uiZ; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalF64Sig(frac); + exp = normExpSig.exp - 1; + frac = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac128 = softfloat_shortShiftLeft128(0, frac, 60); + uiZ.v64 = packToF128UI64(sign, exp + 0x3C00, frac128.v64); + uiZ.v0 = frac128.v0; + return uiZ; +} diff --git a/src/cpu/softfloat3e/f64_to_f16.c b/src/cpu/softfloat3e/f64_to_f16.c new file mode 100644 index 0000000000..fe8dea057a --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_f16.c @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float16 f64_to_f16(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + uint16_t uiZ, frac16; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF16UI(&commonNaN); + } else { + uiZ = packToF16UI(sign, 0x1F, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (!exp && frac) { + if (softfloat_denormalsAreZeros(status)) + return packToF16UI(sign, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac16 = softfloat_shortShiftRightJam64(frac, 38); + if (! (exp | frac16)) { + return packToF16UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF16(sign, exp - 0x3F1, frac16 | 0x4000, status); +} diff --git a/src/cpu/softfloat3e/f64_to_f32.c b/src/cpu/softfloat3e/f64_to_f32.c new file mode 100644 index 0000000000..7ebbf428f3 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_f32.c @@ -0,0 +1,83 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 f64_to_f32(float64 a, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t frac; + struct commonNaN commonNaN; + uint32_t uiZ, frac32; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + frac = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp == 0x7FF) { + if (frac) { + softfloat_f64UIToCommonNaN(a, &commonNaN, status); + uiZ = softfloat_commonNaNToF32UI(&commonNaN); + } else { + uiZ = packToF32UI(sign, 0xFF, 0); + } + return uiZ; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (!exp && frac) { + if (softfloat_denormalsAreZeros(status)) + return packToF32UI(sign, 0, 0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + frac32 = softfloat_shortShiftRightJam64(frac, 22); + if (! (exp | frac32)) { + return packToF32UI(sign, 0, 0); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return softfloat_roundPackToF32(sign, exp - 0x381, frac32 | 0x40000000, status); +} diff --git a/src/cpu/softfloat3e/f64_to_i32.c b/src/cpu/softfloat3e/f64_to_i32.c new file mode 100644 index 0000000000..c296e0bd5e --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_i32.c @@ -0,0 +1,77 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f64_to_i32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow) + if ((exp == 0x7FF) && sig) { +#if (i32_fromNaN == i32_fromPosOverflow) + sign = 0; +#elif (i32_fromNaN == i32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return i32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x427 - exp; + if (0 < shiftDist) sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToI32(sign, sig, roundingMode, exact, status); +} + diff --git a/src/cpu/softfloat3e/f64_to_i32_r_minMag.c b/src/cpu/softfloat3e/f64_to_i32_r_minMag.c new file mode 100644 index 0000000000..80e2d6bc3e --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_i32_r_minMag.c @@ -0,0 +1,89 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t f64_to_i32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint64_t sig; + int16_t shiftDist; + bool sign; + int32_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + if (shiftDist < 22) { + if (sign && (exp == 0x41E) && (sig < UINT64_C(0x0000000000200000))) { + if (exact && sig) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return -0x7FFFFFFF - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && sig + ? i32_fromNaN + : sign ? i32_fromNegOverflow : i32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + absZ = sig>>shiftDist; + if (exact && ((uint64_t) (uint32_t) absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f64_to_i64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x433 - exp; + if (shiftDist <= 0) { + if (shiftDist < -11) goto invalid; + sigExtra.v = sig<<-shiftDist; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + } + return softfloat_roundToI64(sign, sigExtra.v, sigExtra.extra, roundingMode, exact, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && fracF64UI(a) + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; +} + diff --git a/src/cpu/softfloat3e/f64_to_i64_r_minMag.c b/src/cpu/softfloat3e/f64_to_i64_r_minMag.c new file mode 100644 index 0000000000..eb633eb227 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_i64_r_minMag.c @@ -0,0 +1,95 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t f64_to_i64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + uint64_t absZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (shiftDist <= 0) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (shiftDist < -10) { + if (a == packToF64UI(1, 0x43E, 0)) { + return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1; + } + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && sig + ? i64_fromNaN + : sign ? i64_fromNegOverflow : i64_fromPosOverflow; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + absZ = sig<<-shiftDist; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + absZ = sig>>shiftDist; + if (exact && (absZ< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f64_to_ui32(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ +#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow) + if ((exp == 0x7FF) && sig) { +#if (ui32_fromNaN == ui32_fromPosOverflow) + sign = 0; +#elif (ui32_fromNaN == ui32_fromNegOverflow) + sign = 1; +#else + softfloat_raiseFlags(status, softfloat_flag_invalid); + return ui32_fromNaN; +#endif + } +#endif + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x427 - exp; + if (0 < shiftDist) sig = softfloat_shiftRightJam64(sig, shiftDist); + return softfloat_roundToUI32(sign, sig, roundingMode, exact, status); +} diff --git a/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c b/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c new file mode 100644 index 0000000000..7610d7c371 --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_ui32_r_minMag.c @@ -0,0 +1,83 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t f64_to_ui32_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint64_t sig; + int16_t shiftDist; + bool sign; + uint32_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + if (sign || (shiftDist < 21)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && sig + ? ui32_fromNaN + : sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sig |= UINT64_C(0x0010000000000000); + z = sig>>shiftDist; + if (exact && ((uint64_t) z< +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f64_to_ui64(float64 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + bool sign; + int16_t exp; + uint64_t sig; + int16_t shiftDist; + struct uint64_extra sigExtra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + exp = expF64UI(a); + sig = fracF64UI(a); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (exp) sig |= UINT64_C(0x0010000000000000); + else if (softfloat_denormalsAreZeros(status)) sig = 0; + shiftDist = 0x433 - exp; + if (shiftDist <= 0) { + if (shiftDist < -11) goto invalid; + sigExtra.v = sig<<-shiftDist; + sigExtra.extra = 0; + } else { + sigExtra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist); + } + return softfloat_roundToUI64(sign, sigExtra.v, sigExtra.extra, roundingMode, exact, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return (exp == 0x7FF) && fracF64UI(a) + ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c b/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c new file mode 100644 index 0000000000..e7bda4c67e --- /dev/null +++ b/src/cpu/softfloat3e/f64_to_ui64_r_minMag.c @@ -0,0 +1,87 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t f64_to_ui64_r_minMag(float64 a, bool exact, struct softfloat_status_t *status) +{ + int16_t exp; + uint64_t sig; + int16_t shiftDist; + bool sign; + uint64_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + exp = expF64UI(a); + sig = fracF64UI(a); + if (softfloat_denormalsAreZeros(status)) + if (!exp && sig) sig = 0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftDist = 0x433 - exp; + if (53 <= shiftDist) { + if (exact && (exp | sig)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + return 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sign = signF64UI(a); + if (sign) goto invalid; + if (shiftDist <= 0) { + if (shiftDist < -11) goto invalid; + z = (sig | UINT64_C(0x0010000000000000))<<-shiftDist; + } else { + sig |= UINT64_C(0x0010000000000000); + z = sig>>shiftDist; + if (exact && (uint64_t) (sig<<(-shiftDist & 63))) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return + (exp == 0x7FF) && sig ? ui64_fromNaN + : sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; +} diff --git a/src/cpu/softfloat/fpatan.cc b/src/cpu/softfloat3e/fpatan.cc similarity index 59% rename from src/cpu/softfloat/fpatan.cc rename to src/cpu/softfloat3e/fpatan.cc index f33a3ff667..207dc320a7 100644 --- a/src/cpu/softfloat/fpatan.cc +++ b/src/cpu/softfloat3e/fpatan.cc @@ -25,27 +25,31 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "softfloat.h" +#include "specialize.h" + +#include "fpu_trans.h" #include "fpu_constant.h" +#include "poly.h" #define FPATAN_ARR_SIZE 11 -static const float128 float128_one = +static const float128_t float128_one = packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_sqrt3 = +static const float128_t float128_sqrt3 = packFloat128(BX_CONST64(0x3fffbb67ae8584ca), BX_CONST64(0xa73b25742d7078b8)); static const floatx80 floatx80_pi = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235)); -static const float128 float128_pi2 = +static const float128_t float128_pi2 = packFloat128(BX_CONST64(0x3fff921fb54442d1), BX_CONST64(0x8469898CC5170416)); -static const float128 float128_pi4 = +static const float128_t float128_pi4 = packFloat128(BX_CONST64(0x3ffe921fb54442d1), BX_CONST64(0x8469898CC5170416)); -static const float128 float128_pi6 = +static const float128_t float128_pi6 = packFloat128(BX_CONST64(0x3ffe0c152382d736), BX_CONST64(0x58465BB32E0F580F)); -static float128 atan_arr[FPATAN_ARR_SIZE] = +static float128_t atan_arr[FPATAN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /* 3 */ @@ -60,10 +64,10 @@ static float128 atan_arr[FPATAN_ARR_SIZE] = PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618) /* 21 */ }; -extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status); +extern float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); /* |x| < 1/4 */ -static float128 poly_atan(float128 x1, struct float_status_t *status) +static float128_t poly_atan(float128_t x1, softfloat_status_t &status) { /* // 3 5 7 9 11 13 15 17 @@ -86,12 +90,11 @@ static float128 poly_atan(float128 x1, struct float_status_t *status) // atan(x) ~ x * [ p(x) + x * q(x) ] // */ - return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE, status); + return OddPoly(x1, (const float128_t*) atan_arr, FPATAN_ARR_SIZE, status); } // ================================================= -// FPATAN Compute y * log (x) -// 2 +// FPATAN Compute arctan(y/x) // ================================================= // @@ -134,125 +137,129 @@ static float128 poly_atan(float128 x1, struct float_status_t *status) // 3 5 7 9 2n+1 // -floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status) +floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + uint64_t bSig = extF80_fraction(b); + int32_t bExp = extF80_exp(b); + int bSign = extF80_sign(b); int zSign = aSign ^ bSign; if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (bSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b, status); - - if (aSign) { /* return 3PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status); - } - else { /* return PI/4 */ - return roundAndPackFloatx80(80, bSign, - FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); - } + if (aSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); + + if (aSign) /* return 3PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status); + else /* return PI/4 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } - if (aSig && (aExp == 0)) - float_raise(status, float_flag_denormal); + if (aSig && ! aExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); } if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (aSig<<1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (bSig && (bExp == 0)) - float_raise(status, float_flag_denormal); + if (bSig && ! bExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); return_PI_or_ZERO: - if (aSign) { /* return PI */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); - } else { /* return 0 */ - return packFloatx80(bSign, 0, 0); - } + if (aSign) /* return PI */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); + else /* return 0 */ + return packToExtF80(bSign, 0, 0); } - if (bExp == 0) + if (! bExp) { - if (bSig == 0) { - if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal); + if (! bSig) { + if (aSig && ! aExp) softfloat_raiseFlags(&status, softfloat_flag_denormal); goto return_PI_or_ZERO; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0) + if (! aExp) { - if (aSig == 0) /* return PI/2 */ - return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + if (! aSig) /* return PI/2 */ + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); /* |a| = |b| ==> return PI/4 */ - if (aSig == bSig && aExp == bExp) - return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status); + if (aSig == bSig && aExp == bExp) { + if (aSign) + return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status); + else + return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status); + } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ - float128 a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0, status); - float128 b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0, status); - float128 x; + float128_t a128 = softfloat_normRoundPackToF128(0, aExp-0x10, aSig, 0, &status); + float128_t b128 = softfloat_normRoundPackToF128(0, bExp-0x10, bSig, 0, &status); + float128_t x; int swap = 0, add_pi6 = 0, add_pi4 = 0; if (aExp > bExp || (aExp == bExp && aSig > bSig)) { - x = float128_div(b128, a128, status); + x = f128_div(b128, a128, &status); } else { - x = float128_div(a128, b128, status); + x = f128_div(a128, b128, &status); swap = 1; } - Bit32s xExp = extractFloat128Exp(x); + int32_t xExp = expF128UI64(x.v64); if (xExp <= FLOATX80_EXP_BIAS-40) goto approximation_completed; - if (x.hi >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 + if (x.v64 >= BX_CONST64(0x3ffe800000000000)) // 3/4 < x < 1 { /* arctan(x) = arctan((x-1)/(x+1)) + pi/4 */ - float128 t1 = float128_sub(x, float128_one, status); - float128 t2 = float128_add(x, float128_one, status); - x = float128_div(t1, t2, status); + float128_t t1 = f128_sub(x, float128_one, &status); + float128_t t2 = f128_add(x, float128_one, &status); + x = f128_div(t1, t2, &status); add_pi4 = 1; } else @@ -263,26 +270,26 @@ floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status) /* arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6 */ - float128 t1 = float128_mul(x, float128_sqrt3, status); - float128 t2 = float128_add(x, float128_sqrt3, status); - x = float128_sub(t1, float128_one, status); - x = float128_div(x, t2, status); + float128_t t1 = f128_mul(x, float128_sqrt3, &status); + float128_t t2 = f128_add(x, float128_sqrt3, &status); + x = f128_sub(t1, float128_one, &status); + x = f128_div(x, t2, &status); add_pi6 = 1; } } x = poly_atan(x, status); - if (add_pi6) x = float128_add(x, float128_pi6, status); - if (add_pi4) x = float128_add(x, float128_pi4, status); + if (add_pi6) x = f128_add(x, float128_pi6, &status); + if (add_pi4) x = f128_add(x, float128_pi4, &status); approximation_completed: - if (swap) x = float128_sub(float128_pi2, x, status); - floatx80 result = float128_to_floatx80(x, status); + if (swap) x = f128_sub(float128_pi2, x, &status); + floatx80 result = f128_to_extF80(x, &status); if (zSign) floatx80_chs(result); - int rSign = extractFloatx80Sign(result); + int rSign = extF80_sign(result); if (!bSign && rSign) - return floatx80_add(result, floatx80_pi, status); + return extF80_add(result, floatx80_pi, &status); if (bSign && !rSign) - return floatx80_sub(result, floatx80_pi, status); + return extF80_sub(result, floatx80_pi, &status); return result; } diff --git a/src/cpu/softfloat/fprem.cc b/src/cpu/softfloat3e/fprem.cc similarity index 53% rename from src/cpu/softfloat/fprem.cc rename to src/cpu/softfloat3e/fprem.cc index 26637c5c57..2252f12307 100644 --- a/src/cpu/softfloat/fprem.cc +++ b/src/cpu/softfloat3e/fprem.cc @@ -23,100 +23,109 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "fpu_trans.h" #define USE_estimateDiv128To64 -#include "softfloat-macros.h" +#include "softfloat-helpers.h" + +#include "specialize.h" // for softfloat_propagateNaNExtF80UI /* executes single exponent reduction cycle */ -static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1) +static uint64_t remainder_kernel(uint64_t aSig0, uint64_t bSig, int expDiff, uint64_t *zSig0, uint64_t *zSig1) { - Bit64u term0, term1; - Bit64u aSig1 = 0; - + uint128 term, z; + uint64_t aSig1 = 0; shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0); - Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig); - mul64To128(bSig, q, &term0, &term1); - sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { + uint64_t q = estimateDiv128To64(aSig1, aSig0, bSig); + term = softfloat_mul64To128(bSig, q); + z = softfloat_sub128(aSig1, aSig0, term.v64, term.v0); + while ((int64_t) z.v64 < 0) { --q; - add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0); + z = softfloat_add128(z.v64, z.v0, 0, bSig); } + *zSig0 = z.v0; + *zSig1 = z.v64; return q; } -static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding_mode, struct float_status_t *status) +static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, int rounding_mode, struct softfloat_status_t *status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + static const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit32s aExp, bExp, zExp, expDiff; - Bit64u aSig0, aSig1, bSig; + int32_t aExp, bExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0, bSig; int aSign; + struct exp32_sig64 normExpSig; + uint128 term; + *q = 0; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) - { - float_raise(status, float_flag_invalid); + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return -1; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) { - *r = propagateFloatx80NaN(a, b, status); + if ((aSig0<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + *r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status); return -1; } - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return -1; } if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) { - *r = propagateFloatx80NaN(a, b, status); + if (bSig << 1) { + *r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status); return -1; } - if (aExp == 0 && aSig0) { - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); - *r = (a.fraction & BX_CONST64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; + if (! aExp && aSig0) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; + *r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; return 0; } *r = a; return 0; } - if (bExp == 0) { - if (bSig == 0) { - float_raise(status, float_flag_invalid); + if (! bExp) { + if (! bSig) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return -1; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0) { - if (aSig0 == 0) { + if (! aExp) { + if (! aSig0) { *r = a; return 0; } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } - expDiff = aExp - bExp; - aSig1 = 0; - Bit32u overflow = 0; + expDiff = aExp - bExp; + int overflow = 0; if (expDiff >= 64) { int n = (expDiff & 0x1f) | 0x20; @@ -129,11 +138,10 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding if (expDiff < 0) { if (expDiff < -1) { - *r = (a.fraction & BX_CONST64(0x8000000000000000)) ? - packFloatx80(aSign, aExp, aSig0) : a; + *r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a; return 0; } - shift128Right(aSig0, 0, 1, &aSig0, &aSig1); + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } @@ -147,26 +155,28 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding } } - if (rounding_mode == float_round_nearest_even) - { - Bit64u term0, term1; - shift128Right(bSig, 0, 1, &term0, &term1); - - if (! lt128(aSig0, aSig1, term0, term1)) - { - int lt = lt128(term0, term1, aSig0, aSig1); - int eq = eq128(aSig0, aSig1, term0, term1); - - if ((eq && ((*q) & 1)) || lt) { - aSign = !aSign; - ++(*q); - } - if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1); + if (rounding_mode == softfloat_round_near_even) { + uint64_t term0, term1; + shortShift128Right(bSig, 0, 1, &term0, &term1); + + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); + + if ((eq && ((*q) & 1)) || lt) { + aSign = !aSign; + ++(*q); + } + if (lt) { + term = softfloat_sub128(bSig, 0, aSig0, aSig1); + aSig0 = term.v64; + aSig1 = term.v0; + } } } } - *r = normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status); + *r = softfloat_normRoundPackToExtF80(aSign, zExp, aSig0, aSig1, 80, status); return overflow; } @@ -176,9 +186,9 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, int rounding | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. *----------------------------------------------------------------------------*/ -int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status) +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status) { - return do_fprem(a, b, r, q, float_round_nearest_even, status); + return do_fprem(a, b, r, q, softfloat_round_near_even, status); } /*---------------------------------------------------------------------------- @@ -190,7 +200,7 @@ int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, s | quotient of 'a' divided by 'b' to an integer. *----------------------------------------------------------------------------*/ -int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status) +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status) { - return do_fprem(a, b, r, q, float_round_to_zero, status); + return do_fprem(a, b, r, q, softfloat_round_to_zero, status); } diff --git a/src/cpu/softfloat/fpu_constant.h b/src/cpu/softfloat3e/fpu_constant.h similarity index 98% rename from src/cpu/softfloat/fpu_constant.h rename to src/cpu/softfloat3e/fpu_constant.h index 7a7fc6f1aa..d7d44ee3c1 100644 --- a/src/cpu/softfloat/fpu_constant.h +++ b/src/cpu/softfloat3e/fpu_constant.h @@ -24,7 +24,7 @@ these four paragraphs for those parts of this code that are retained. #include "config.h" // Pentium CPU uses only 68-bit precision M_PI approximation -//#define BETTER_THAN_PENTIUM +// #define BETTER_THAN_PENTIUM /*============================================================================ * Written for Bochs (x86 achitecture simulator) by diff --git a/src/cpu/softfloat3e/fpu_trans.h b/src/cpu/softfloat3e/fpu_trans.h new file mode 100644 index 0000000000..bd3d3cecba --- /dev/null +++ b/src/cpu/softfloat3e/fpu_trans.h @@ -0,0 +1,117 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003-2018 Stanislav Shwartsman +// Written by Stanislav Shwartsman [sshwarts at sourceforge net] +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +///////////////////////////////////////////////////////////////////////// + +#ifndef _FPU_TRANS_H_ +#define _FPU_TRANS_H_ + +#include "softfloat.h" +#include "softfloat-specialize.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision operations. +*----------------------------------------------------------------------------*/ + +int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status); +int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, uint64_t *q, struct softfloat_status_t *status); + +floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status); +#ifdef __cplusplus +floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status); +floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status); +floatx80 fpatan(floatx80 a, floatx80 b, softfloat_status_t &status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision trigonometric functions. +*----------------------------------------------------------------------------*/ + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status); +int fsin(floatx80 &a, softfloat_status_t &status); +int fcos(floatx80 &a, softfloat_status_t &status); +int ftan(floatx80 &a, softfloat_status_t &status); +#else +floatx80 fyl2x(floatx80 a, floatx80 b, struct softfloat_status_t *status); +floatx80 fyl2xp1(floatx80 a, floatx80 b, struct softfloat_status_t *status); +floatx80 fpatan(floatx80 a, floatx80 b, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE extended double-precision trigonometric functions. +*----------------------------------------------------------------------------*/ + +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct softfloat_status_t *status); +int fsin(floatx80 *a, struct softfloat_status_t *status); +int fcos(floatx80 *a, struct softfloat_status_t *status); +int ftan(floatx80 *a, struct softfloat_status_t *status); +#endif + +#ifdef __cplusplus +} +#endif + +/*----------------------------------------------------------------------------- +| Calculates the absolute value of the extended double-precision floating-point +| value `a'. The operation is performed according to the IEC/IEEE Standard +| for Binary Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +static __inline floatx80 &floatx80_abs(floatx80 ®) +#else +static __inline floatx80 floatx80_abs(floatx80 reg) +#endif +{ + reg.signExp &= 0x7FFF; + return reg; +} + +/*----------------------------------------------------------------------------- +| Changes the sign of the extended double-precision floating-point value 'a'. +| The operation is performed according to the IEC/IEEE Standard for Binary +| Floating-Point Arithmetic. +*----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +static __inline floatx80 &floatx80_chs(floatx80 ®) +#else +static __inline floatx80 floatx80_chs(floatx80 reg) +#endif +{ + reg.signExp ^= 0x8000; + return reg; +} + +#ifdef __cplusplus +static __inline floatx80 FPU_round_const(const floatx80 &a, int adj) +#else +static __inline floatx80 FPU_round_const(const floatx80 a, int adj) +#endif +{ + floatx80 result = a; + result.signif += adj; + return result; +} + +#endif diff --git a/src/cpu/softfloat/fsincos.cc b/src/cpu/softfloat3e/fsincos.cc similarity index 68% rename from src/cpu/softfloat/fsincos.cc rename to src/cpu/softfloat3e/fsincos.cc index f5b33a8230..1a2a018de8 100644 --- a/src/cpu/softfloat/fsincos.cc +++ b/src/cpu/softfloat3e/fsincos.cc @@ -26,24 +26,29 @@ these four paragraphs for those parts of this code that are retained. #define FLOAT128 #define USE_estimateDiv128To64 -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "specialize.h" + +#include "fpu_trans.h" +#include "softfloat-helpers.h" #include "fpu_constant.h" +#include "poly.h" + static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); /* reduce trigonometric function argument using 128-bit precision M_PI approximation */ -static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1) +static uint64_t argument_reduction_kernel(uint64_t aSig0, int Exp, uint64_t *zSig0, uint64_t *zSig1) { - Bit64u term0, term1, term2; - Bit64u aSig1 = 0; + uint64_t term0, term1, term2; + uint64_t aSig1 = 0; shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0); - Bit64u q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); + uint64_t q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI); mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2); sub128(aSig1, aSig0, term0, term1, zSig1, zSig0); - while ((Bit64s)(*zSig1) < 0) { + while ((int64_t)(*zSig1) < 0) { --q; add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2); } @@ -51,35 +56,35 @@ static Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bi return q; } -static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1) +static int reduce_trig_arg(int expDiff, int &zSign, uint64_t &aSig0, uint64_t &aSig1) { - Bit64u term0, term1, q = 0; + uint64_t term0, term1, q = 0; if (expDiff < 0) { - shift128Right(*aSig0, 0, 1, aSig0, aSig1); + shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1); expDiff = 0; } if (expDiff > 0) { - q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1); + q = argument_reduction_kernel(aSig0, expDiff, &aSig0, &aSig1); } else { - if (FLOAT_PI_HI <= *aSig0) { - *aSig0 -= FLOAT_PI_HI; + if (FLOAT_PI_HI <= aSig0) { + aSig0 -= FLOAT_PI_HI; q = 1; } } - shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); - if (! lt128(*aSig0, *aSig1, term0, term1)) + shortShift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1); + if (! softfloat_lt128(aSig0, aSig1, term0, term1)) { - int lt = lt128(term0, term1, *aSig0, *aSig1); - int eq = eq128(*aSig0, *aSig1, term0, term1); + int lt = softfloat_lt128(term0, term1, aSig0, aSig1); + int eq = softfloat_eq128(aSig0, aSig1, term0, term1); if ((eq && (q & 1)) || lt) { - *zSign = !(*zSign); + zSign = !zSign; ++q; } - if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1); + if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, aSig0, aSig1, &aSig0, &aSig1); } return (int)(q & 3); @@ -88,7 +93,7 @@ static int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1 #define SIN_ARR_SIZE 11 #define COS_ARR_SIZE 11 -static float128 sin_arr[SIN_ARR_SIZE] = +static float128_t sin_arr[SIN_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /* 3 */ @@ -103,7 +108,7 @@ static float128 sin_arr[SIN_ARR_SIZE] = PACK_FLOAT_128(0x3fbd71b8ef6dcf57, 0x18bef146fcee6e45) /* 21 */ }; -static float128 cos_arr[COS_ARR_SIZE] = +static float128_t cos_arr[COS_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 0 */ PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /* 2 */ @@ -118,10 +123,8 @@ static float128 cos_arr[COS_ARR_SIZE] = PACK_FLOAT_128(0x3fc1e542ba402022, 0x507a9cad2bf8f0bb) /* 20 */ }; -extern float128 OddPoly (float128 x, float128 *arr, int n, struct float_status_t *status); - /* 0 <= x <= pi/4 */ -BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status) +static __inline float128_t poly_sin(float128_t x, softfloat_status_t &status) { // 3 5 7 9 11 13 15 // x x x x x x x @@ -143,13 +146,11 @@ BX_CPP_INLINE float128 poly_sin(float128 x, struct float_status_t *status) // sin(x) ~ x * [ p(x) + x * q(x) ] // - return OddPoly(x, sin_arr, SIN_ARR_SIZE, status); + return OddPoly(x, (const float128_t*) sin_arr, SIN_ARR_SIZE, status); } -extern float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status); - /* 0 <= x <= pi/4 */ -BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status) +static __inline float128_t poly_cos(float128_t x, softfloat_status_t &status) { // 2 4 6 8 10 12 14 // x x x x x x x @@ -166,22 +167,22 @@ BX_CPP_INLINE float128 poly_cos(float128 x, struct float_status_t *status) // cos(x) ~ [ p(x) + x * q(x) ] // - return EvenPoly(x, cos_arr, COS_ARR_SIZE, status); + return EvenPoly(x, (const float128_t*) cos_arr, COS_ARR_SIZE, status); } -BX_CPP_INLINE void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) +static __inline void sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) { if (sin_a) *sin_a = a; if (cos_a) *cos_a = a; } -BX_CPP_INLINE void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) +static __inline void sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a) { if (sin_a) *sin_a = a; if (cos_a) *cos_a = floatx80_one; } -static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struct float_status_t *status) +static floatx80 sincos_approximation(int neg, float128_t r, uint64_t quotient, softfloat_status_t &status) { if (quotient & 0x1) { r = poly_cos(r, status); @@ -190,7 +191,7 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struc r = poly_sin(r, status); } - floatx80 result = float128_to_floatx80(r, status); + floatx80 result = f128_to_extF80(r, &status); if (quotient & 0x2) neg = ! neg; @@ -220,59 +221,62 @@ static floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient, struc // sin(x+2pi) = sin(x) // -int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status) +int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit64u aSig0, aSig1 = 0; - Bit32s aExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0; + int32_t aExp, zExp, expDiff; int aSign, zSign; int q = 0; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a)) { + if (extF80_isUnsupported(a)) { goto invalid; } - aSig0 = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); /* invalid argument */ if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) { - sincos_invalid(sin_a, cos_a, propagateFloatx80NaNOne(a, status)); + if (aSig0 << 1) { + sincos_invalid(sin_a, cos_a, softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status)); return 0; } invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); sincos_invalid(sin_a, cos_a, floatx80_default_nan); return 0; } - if (aExp == 0) { - if (aSig0 == 0) { + if (! aExp) { + if (! aSig0) { sincos_tiny_argument(sin_a, cos_a, a); return 0; } - float_raise(status, float_flag_denormal); + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (sin_a) - float_raise(status, float_flag_underflow); + softfloat_raiseFlags(&status, softfloat_flag_underflow); sincos_tiny_argument(sin_a, cos_a, a); return 0; } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } zSign = aSign; @@ -283,7 +287,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t if (expDiff >= 63) return -1; - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { @@ -294,7 +298,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t zExp = aExp; } else { - q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); + q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ @@ -302,7 +306,7 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t /* **************************** */ /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status); if (aSign) q = -q; if (sin_a) *sin_a = sincos_approximation(zSign, r, q, status); @@ -311,14 +315,14 @@ int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t return 0; } -int fsin(floatx80 *a, struct float_status_t *status) +int fsin(floatx80 &a, softfloat_status_t &status) { - return fsincos(*a, a, 0, status); + return fsincos(a, &a, 0, status); } -int fcos(floatx80 *a, struct float_status_t *status) +int fcos(floatx80 &a, softfloat_status_t &status) { - return fsincos(*a, 0, a, status); + return fsincos(a, 0, &a, status); } // ================================================= @@ -348,51 +352,55 @@ int fcos(floatx80 *a, struct float_status_t *status) // cos(x) // -int ftan(floatx80 *a, struct float_status_t *status) +int ftan(floatx80 &a, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit64u aSig0, aSig1 = 0; - Bit32s aExp, zExp, expDiff; + uint64_t aSig0, aSig1 = 0; + int32_t aExp, zExp, expDiff; int aSign, zSign; int q = 0; // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(*a)) { + if (extF80_isUnsupported(a)) { goto invalid; } - aSig0 = extractFloatx80Frac(*a); - aExp = extractFloatx80Exp(*a); - aSign = extractFloatx80Sign(*a); + aSig0 = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); /* invalid argument */ if (aExp == 0x7FFF) { - if ((Bit64u) (aSig0<<1)) + if (aSig0 << 1) { - *a = propagateFloatx80NaNOne(*a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, aSig0, 0, 0, &status); return 0; } invalid: - float_raise(status, float_flag_invalid); - *a = floatx80_default_nan; + softfloat_raiseFlags(&status, softfloat_flag_invalid); + a = floatx80_default_nan; return 0; } - if (aExp == 0) { - if (aSig0 == 0) return 0; - float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig0) return 0; + softfloat_raiseFlags(&status, softfloat_flag_denormal); /* handle pseudo denormals */ if (! (aSig0 & BX_CONST64(0x8000000000000000))) { - float_raise(status, float_flag_inexact | float_flag_underflow); + softfloat_raiseFlags(&status, softfloat_flag_inexact | softfloat_flag_underflow); return 0; } - normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0); + + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig0); + aExp = normExpSig.exp + 1; + aSig0 = normExpSig.sig; } zSign = aSign; @@ -403,17 +411,17 @@ int ftan(floatx80 *a, struct float_status_t *status) if (expDiff >= 63) return -1; - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (expDiff < -1) { // doesn't require reduction if (expDiff <= -68) { - *a = packFloatx80(aSign, aExp, aSig0); + a = packFloatx80(aSign, aExp, aSig0); return 0; } zExp = aExp; } else { - q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1); + q = reduce_trig_arg(expDiff, zSign, aSig0, aSig1); } /* **************************** */ @@ -421,21 +429,21 @@ int ftan(floatx80 *a, struct float_status_t *status) /* **************************** */ /* using float128 for approximation */ - float128 r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1, status); + float128_t r = softfloat_normRoundPackToF128(0, zExp-0x10, aSig0, aSig1, &status); - float128 sin_r = poly_sin(r, status); - float128 cos_r = poly_cos(r, status); + float128_t sin_r = poly_sin(r, status); + float128_t cos_r = poly_cos(r, status); if (q & 0x1) { - r = float128_div(cos_r, sin_r, status); + r = f128_div(cos_r, sin_r, &status); zSign = ! zSign; } else { - r = float128_div(sin_r, cos_r, status); + r = f128_div(sin_r, cos_r, &status); } - *a = float128_to_floatx80(r, status); + a = f128_to_extF80(r, &status); if (zSign) - floatx80_chs(*a); + floatx80_chs(a); return 0; } diff --git a/src/cpu/softfloat/fyl2x.cc b/src/cpu/softfloat3e/fyl2x.cc similarity index 61% rename from src/cpu/softfloat/fyl2x.cc rename to src/cpu/softfloat3e/fyl2x.cc index 875f866a91..7c90e6207f 100644 --- a/src/cpu/softfloat/fyl2x.cc +++ b/src/cpu/softfloat3e/fyl2x.cc @@ -24,29 +24,28 @@ these four paragraphs for those parts of this code that are retained. * ==========================================================================*/ #define FLOAT128 - -#include "softfloatx80.h" -#include "softfloat-round-pack.h" +#include "config.h" +#include "fpu_trans.h" +#include "specialize.h" +#include "softfloat-helpers.h" #include "fpu_constant.h" +#include "poly.h" -static const floatx80 floatx80_one = - packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); +static const floatx80 floatx80_one = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000)); -static const float128 float128_one = +static const float128_t float128_one = packFloat128(BX_CONST64(0x3fff000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_two = +static const float128_t float128_two = packFloat128(BX_CONST64(0x4000000000000000), BX_CONST64(0x0000000000000000)); -static const float128 float128_ln2inv2 = +static const float128_t float128_ln2inv2 = packFloat128(BX_CONST64(0x400071547652b82f), BX_CONST64(0xe1777d0ffda0d23a)); #define SQRT2_HALF_SIG BX_CONST64(0xb504f333f9de6484) -extern float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status); - #define L2_ARR_SIZE 9 -static float128 ln_arr[L2_ARR_SIZE] = +static float128_t ln_arr[L2_ARR_SIZE] = { PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */ PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /* 3 */ @@ -59,7 +58,7 @@ static float128 ln_arr[L2_ARR_SIZE] = PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2) /* 17 */ }; -static float128 poly_ln(float128 x1, struct float_status_t *status) +static float128_t poly_ln(float128_t x1, softfloat_status_t &status) { /* // @@ -84,28 +83,28 @@ static float128 poly_ln(float128 x1, struct float_status_t *status) // 1-u // */ - return OddPoly(x1, ln_arr, L2_ARR_SIZE, status); + return OddPoly(x1, (const float128_t*) ln_arr, L2_ARR_SIZE, status); } /* required sqrt(2)/2 < x < sqrt(2) */ -static float128 poly_l2(float128 x, struct float_status_t *status) +static float128_t poly_l2(float128_t x, softfloat_status_t &status) { /* using float128 for approximation */ - float128 x_p1 = float128_add(x, float128_one, status); - float128 x_m1 = float128_sub(x, float128_one, status); - x = float128_div(x_m1, x_p1, status); + float128_t x_p1 = f128_add(x, float128_one, &status); + float128_t x_m1 = f128_sub(x, float128_one, &status); + x = f128_div(x_m1, x_p1, &status); x = poly_ln(x, status); - x = float128_mul(x, float128_ln2inv2, status); + x = f128_mul(x, float128_ln2inv2, &status); return x; } -static float128 poly_l2p1(float128 x, struct float_status_t *status) +static float128_t poly_l2p1(float128_t x, softfloat_status_t &status) { /* using float128 for approximation */ - float128 x_p2 = float128_add(x, float128_two, status); - x = float128_div(x, x_p2, status); + float128_t x_plus2 = f128_add(x, float128_two, &status); + x = f128_div(x, x_plus2, &status); x = poly_ln(x, status); - x = float128_mul(x, float128_ln2inv2, status); + x = f128_mul(x, float128_ln2inv2, &status); return x; } @@ -134,7 +133,7 @@ static float128 poly_l2p1(float128 x, struct float_status_t *status) // 1-u 3 5 7 2n+1 // -floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) +floatx80 fyl2x(floatx80 a, floatx80 b, softfloat_status_t &status) { /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. @@ -142,71 +141,73 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - Bit64u aSig = extractFloatx80Frac(a); - Bit32s aExp = extractFloatx80Exp(a); - int aSign = extractFloatx80Sign(a); - Bit64u bSig = extractFloatx80Frac(b); - Bit32s bExp = extractFloatx80Exp(b); - int bSign = extractFloatx80Sign(b); + uint64_t aSig = extF80_fraction(a); + int32_t aExp = extF80_exp(a); + int aSign = extF80_sign(a); + uint64_t bSig = extF80_fraction(b); + int32_t bExp = extF80_exp(b); + int bSign = extF80_sign(b); int zSign = bSign ^ 1; if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); + if ((aSig<<1) || ((bExp == 0x7FFF) && (bSig<<1))) { + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); } if (aSign) goto invalid; else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! bExp) { + if (! bSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } } - if (bExp == 0x7FFF) - { - if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status); - if (aSign && (Bit64u)(aExp | aSig)) goto invalid; - if (aSig && (aExp == 0)) - float_raise(status, float_flag_denormal); + if (bExp == 0x7FFF) { + if (bSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); + if (aSign && (uint64_t)(aExp | aSig)) goto invalid; + if (aSig && ! aExp) + softfloat_raiseFlags(&status, softfloat_flag_denormal); if (aExp < 0x3FFF) { return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid; + if (aExp == 0x3FFF && ! (aSig<<1)) goto invalid; return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0) { - if (aSig == 0) { + if (! aExp) { + if (! aSig) { if ((bExp | bSig) == 0) goto invalid; - float_raise(status, float_flag_divbyzero); + softfloat_raiseFlags(&status, softfloat_flag_divbyzero); return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } if (aSign) goto invalid; - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } if (aSign) goto invalid; - if (bExp == 0) { - if (bSig == 0) { + if (! bExp) { + if (! bSig) { if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0); return packFloatx80(bSign, 0, 0); } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) + if (aExp == 0x3FFF && ! (aSig<<1)) return packFloatx80(bSign, 0, 0); - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); int ExpDiff = aExp - 0x3FFF; aExp = 0; @@ -219,12 +220,15 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) /* using float128 for approximation */ /* ******************************** */ - Bit64u zSig0, zSig1; - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128Four(0, aExp+0x3FFF, zSig0, zSig1); + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status); + + uint64_t zSig0, zSig1; + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1); x = poly_l2(x, status); - x = float128_add(x, int64_to_float128((Bit64s) ExpDiff), status); - return floatx80_128_mul(b, x, status); + x = f128_add(x, i32_to_f128(ExpDiff), &status); + x = f128_mul(x, b128, &status); + return f128_to_extF80(x, &status); } // ================================================= @@ -252,112 +256,117 @@ floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status) // 1-u 3 5 7 2n+1 // -floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status) +floatx80 fyl2xp1(floatx80 a, floatx80 b, softfloat_status_t &status) { + int32_t aExp, bExp; + uint64_t aSig, bSig, zSig0, zSig1, zSig2; + int aSign, bSign; + /*---------------------------------------------------------------------------- | The pattern for a default generated extended double-precision NaN. *----------------------------------------------------------------------------*/ const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - Bit32s aExp, bExp; - Bit64u aSig, bSig, zSig0, zSig1, zSig2; - int aSign, bSign; - // handle unsupported extended double-precision floating encodings - if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b)) { + if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) { invalid: - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(&status, softfloat_flag_invalid); return floatx80_default_nan; } - aSig = extractFloatx80Frac(a); - aExp = extractFloatx80Exp(a); - aSign = extractFloatx80Sign(a); - bSig = extractFloatx80Frac(b); - bExp = extractFloatx80Exp(b); - bSign = extractFloatx80Sign(b); + + aSig = extF80_fraction(a); + aExp = extF80_exp(a); + aSign = extF80_sign(a); + bSig = extF80_fraction(b); + bExp = extF80_exp(b); + bSign = extF80_sign(b); int zSign = aSign ^ bSign; if (aExp == 0x7FFF) { - if ((Bit64u) (aSig<<1) - || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) - { - return propagateFloatx80NaN(a, b, status); + if ((aSig<<1) != 0 || ((bExp == 0x7FFF) && (bSig<<1) != 0)) { + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); } if (aSign) goto invalid; else { - if (bExp == 0) { - if (bSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! bExp) { + if (! bSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } } if (bExp == 0x7FFF) { - if ((Bit64u) (bSig<<1)) - return propagateFloatx80NaN(a, b, status); + if (bSig << 1) + return softfloat_propagateNaNExtF80UI(a.signExp, aSig, b.signExp, bSig, &status); - if (aExp == 0) { - if (aSig == 0) goto invalid; - float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig) goto invalid; + softfloat_raiseFlags(&status, softfloat_flag_denormal); } return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000)); } - if (aExp == 0) { - if (aSig == 0) { - if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal); + if (! aExp) { + if (! aSig) { + if (bSig && ! bExp) softfloat_raiseFlags(&status, softfloat_flag_denormal); return packFloatx80(zSign, 0, 0); } - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(aSig, &aExp, &aSig); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(aSig); + aExp = normExpSig.exp + 1; + aSig = normExpSig.sig; } - if (bExp == 0) { - if (bSig == 0) return packFloatx80(zSign, 0, 0); - float_raise(status, float_flag_denormal); - normalizeFloatx80Subnormal(bSig, &bExp, &bSig); + if (! bExp) { + if (! bSig) return packFloatx80(zSign, 0, 0); + softfloat_raiseFlags(&status, softfloat_flag_denormal); + struct exp32_sig64 normExpSig = softfloat_normSubnormalExtF80Sig(bSig); + bExp = normExpSig.exp + 1; + bSig = normExpSig.sig; } - float_raise(status, float_flag_inexact); + softfloat_raiseFlags(&status, softfloat_flag_inexact); if (aSign && aExp >= 0x3FFF) return a; if (aExp >= 0x3FFC) // big argument { - return fyl2x(floatx80_add(a, floatx80_one, status), b, status); + return fyl2x(extF80_add(a, floatx80_one, &status), b, status); } // handle tiny argument if (aExp < FLOATX80_EXP_BIAS-70) { // first order approximation, return (a*b)/ln(2) - Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; + int32_t zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE; - mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { + mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } zExp = zExp + bExp - 0x3FFE; - mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); - if (0 < (Bit64s) zSig0) { + mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2); + if (0 < (int64_t) zSig0) { shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1); --zExp; } - return - roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1, status); + return softfloat_roundPackToExtF80(aSign ^ bSign, zExp, zSig0, zSig1, 80, &status); } /* ******************************** */ /* using float128 for approximation */ /* ******************************** */ - shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); - float128 x = packFloat128Four(aSign, aExp, zSig0, zSig1); + float128_t b128 = softfloat_normRoundPackToF128(bSign, bExp-0x10, bSig, 0, &status); + + shortShift128Right(aSig<<1, 0, 16, &zSig0, &zSig1); + float128_t x = packFloat128(aSign, aExp, zSig0, zSig1); x = poly_l2p1(x, status); - return floatx80_128_mul(b, x, status); + x = f128_mul(x, b128, &status); + return f128_to_extF80(x, &status); } diff --git a/src/cpu/softfloat3e/i32_to_extF80.cc b/src/cpu/softfloat3e/i32_to_extF80.cc new file mode 100644 index 0000000000..edd92ced0e --- /dev/null +++ b/src/cpu/softfloat3e/i32_to_extF80.cc @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t i32_to_extF80(int32_t a) +{ + uint16_t uiZ64; + uint32_t absA; + bool sign; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + absA = 0; + if (a) { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA); + uiZ64 = packToExtF80UI64(sign, 0x401E - shiftDist); + absA <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = (uint64_t) absA<<32; + return z; +} diff --git a/src/cpu/softfloat3e/i32_to_f128.cc b/src/cpu/softfloat3e/i32_to_f128.cc new file mode 100644 index 0000000000..1ae64e46b7 --- /dev/null +++ b/src/cpu/softfloat3e/i32_to_f128.cc @@ -0,0 +1,59 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t i32_to_f128(int32_t a) +{ + uint64_t uiZ64; + bool sign; + uint32_t absA; + int8_t shiftDist; + float128_t z; + + uiZ64 = 0; + if (a) { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA) + 17; + uiZ64 = packToF128UI64(sign, 0x402E - shiftDist, (uint64_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 i32_to_f16(int32_t a, struct softfloat_status_t *status) +{ + bool sign; + uint32_t absA; + int8_t shiftDist; + uint16_t sig; + + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA) - 21; + if (0 <= shiftDist) { + return a ? packToF16UI(sign, 0x18 - shiftDist, (uint16_t) absA<>(-shiftDist) | ((uint32_t) (absA<<(shiftDist & 31)) != 0) + : (uint16_t) absA< +#include +#include "internals.h" +#include "softfloat.h" + +float32 i32_to_f32(int32_t a, struct softfloat_status_t *status) +{ + bool sign; + uint32_t absA; + + sign = (a < 0); + if (! (a & 0x7FFFFFFF)) { + return sign ? packToF32UI(1, 0x9E, 0) : 0; + } + absA = sign ? -(uint32_t) a : (uint32_t) a; + return softfloat_normRoundPackToF32(sign, 0x9C, absA, status); +} diff --git a/src/cpu/softfloat3e/i32_to_f64.c b/src/cpu/softfloat3e/i32_to_f64.c new file mode 100644 index 0000000000..7aaa4e1c28 --- /dev/null +++ b/src/cpu/softfloat3e/i32_to_f64.c @@ -0,0 +1,56 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 i32_to_f64(int32_t a) +{ + bool sign; + uint32_t absA; + int8_t shiftDist; + + if (! a) { + return 0; + } else { + sign = (a < 0); + absA = sign ? -(uint32_t) a : (uint32_t) a; + shiftDist = softfloat_countLeadingZeros32(absA) + 21; + return packToF64UI(sign, 0x432 - shiftDist, (uint64_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t i64_to_extF80(int64_t a) +{ + uint16_t uiZ64; + uint64_t absA; + bool sign; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + absA = 0; + if (a) { + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA); + uiZ64 = packToExtF80UI64(sign, 0x403E - shiftDist); + absA <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = absA; + return z; +} diff --git a/src/cpu/softfloat3e/i64_to_f128.cc b/src/cpu/softfloat3e/i64_to_f128.cc new file mode 100644 index 0000000000..4d80a9e7ab --- /dev/null +++ b/src/cpu/softfloat3e/i64_to_f128.cc @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t i64_to_f128(int64_t a) +{ + uint64_t uiZ64, uiZ0; + bool sign; + uint64_t absA; + int8_t shiftDist; + struct uint128 zSig; + float128_t z; + + if (! a) { + uiZ64 = 0; + uiZ0 = 0; + } else { + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA) + 49; + if (64 <= shiftDist) { + zSig.v64 = absA<<(shiftDist - 64); + zSig.v0 = 0; + } else { + zSig = softfloat_shortShiftLeft128(0, absA, shiftDist); + } + uiZ64 = packToF128UI64(sign, 0x406E - shiftDist, zSig.v64); + uiZ0 = zSig.v0; + } + z.v64 = uiZ64; + z.v0 = uiZ0; + return z; +} diff --git a/src/cpu/softfloat3e/i64_to_f16.c b/src/cpu/softfloat3e/i64_to_f16.c new file mode 100644 index 0000000000..43873610a4 --- /dev/null +++ b/src/cpu/softfloat3e/i64_to_f16.c @@ -0,0 +1,61 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 i64_to_f16(int64_t a, struct softfloat_status_t *status) +{ + bool sign; + uint64_t absA; + int8_t shiftDist; + uint16_t sig; + + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA) - 53; + if (0 <= shiftDist) { + return a ? packToF16UI(sign, 0x18 - shiftDist, (uint16_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float32 i64_to_f32(int64_t a, struct softfloat_status_t *status) +{ + bool sign; + uint64_t absA; + int8_t shiftDist; + uint32_t sig; + + sign = (a < 0); + absA = sign ? -(uint64_t) a : (uint64_t) a; + shiftDist = softfloat_countLeadingZeros64(absA) - 40; + if (0 <= shiftDist) { + return a ? packToF32UI(sign, 0x95 - shiftDist, (uint32_t) absA< +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 i64_to_f64(int64_t a, struct softfloat_status_t *status) +{ + bool sign; + uint64_t absA; + + sign = (a < 0); + if (! (a & UINT64_C(0x7FFFFFFFFFFFFFFF))) { + return sign ? packToF64UI(1, 0x43E, 0) : 0; + } + absA = sign ? -(uint64_t) a : (uint64_t) a; + return softfloat_normRoundPackToF64(sign, 0x43C, absA, status); +} diff --git a/src/cpu/softfloat3e/internals.h b/src/cpu/softfloat3e/internals.h new file mode 100644 index 0000000000..3b5d7aa4d5 --- /dev/null +++ b/src/cpu/softfloat3e/internals.h @@ -0,0 +1,150 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _INTERNALS_H_ +#define _INTERNALS_H_ + +#include +#include +//#include "primitives.h" +#include "softfloat_types.h" + +struct softfloat_status_t; + +#ifdef __cplusplus +extern "C" { +#endif + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +uint32_t softfloat_roundToUI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t softfloat_roundToUI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); + +int32_t softfloat_roundToI32(bool, uint64_t, uint8_t, bool, struct softfloat_status_t *); +int64_t softfloat_roundToI64(bool, uint64_t, uint64_t, uint8_t, bool, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + + +#define signF16UI(a) ((bool) ((uint16_t) (a)>>15)) +#define expF16UI(a) ((int8_t) ((a)>>10) & 0x1F) +#define fracF16UI(a) ((a) & 0x03FF) +#define packToF16UI(sign, exp, sig) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig)) + +#define isNaNF16UI(a) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF)) + +struct exp8_sig16 { int8_t exp; uint16_t sig; }; +struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t); + +float16 softfloat_roundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); +float16 softfloat_normRoundPackToF16(bool, int16_t, uint16_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF32UI(a) ((bool) ((uint32_t) (a)>>31)) +#define expF32UI(a) ((int16_t) ((a)>>23) & 0xFF) +#define fracF32UI(a) ((a) & 0x007FFFFF) +#define packToF32UI(sign, exp, sig) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig)) + +#define isNaNF32UI(a) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF)) + +struct exp16_sig32 { int16_t exp; uint32_t sig; }; +struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t); + +float32 softfloat_roundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); +float32 softfloat_normRoundPackToF32(bool, int16_t, uint32_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF64UI(a) ((bool) ((uint64_t) (a)>>63)) +#define expF64UI(a) ((int16_t) ((a)>>52) & 0x7FF) +#define fracF64UI(a) ((a) & UINT64_C(0x000FFFFFFFFFFFFF)) +#define packToF64UI(sign, exp, sig) ((uint64_t) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<52) + (sig))) + +#define isNaNF64UI(a) (((~(a) & UINT64_C(0x7FF0000000000000)) == 0) && ((a) & UINT64_C(0x000FFFFFFFFFFFFF))) + +struct exp16_sig64 { int16_t exp; uint64_t sig; }; +struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t); + +float64 softfloat_roundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); +float64 softfloat_normRoundPackToF64(bool, int16_t, uint64_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status); +extFloat80_t softfloat_subMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status); + +#define signExtF80UI64(a64) ((bool) ((uint16_t) (a64)>>15)) +#define expExtF80UI64(a64) ((a64) & 0x7FFF) +#define packToExtF80UI64(sign, exp) ((uint16_t) (sign)<<15 | (exp)) + +#define isNaNExtF80UI(a64, a0) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C(0x7FFFFFFFFFFFFFFF))) + +extFloat80_t packToExtF80(bool, uint16_t, uint64_t); +extFloat80_t packToExtF80_twoargs(uint16_t, uint64_t); +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ + +struct exp32_sig64 { int32_t exp; uint64_t sig; }; +struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t); + +extFloat80_t + softfloat_roundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *); +extFloat80_t + softfloat_normRoundPackToExtF80(bool, int32_t, uint64_t, uint64_t, uint8_t, struct softfloat_status_t *); + +/*---------------------------------------------------------------------------- +*----------------------------------------------------------------------------*/ +#define signF128UI64(a64) ((bool) ((uint64_t) (a64)>>63)) +#define expF128UI64(a64) ((int32_t) ((a64)>>48) & 0x7FFF) +#define fracF128UI64(a64) ((a64) & UINT64_C(0x0000FFFFFFFFFFFF)) +#define packToF128UI64(sign, exp, sig64) (((uint64_t) (sign)<<63) + ((uint64_t) (exp)<<48) + (sig64)) + +#define isNaNF128UI(a64, a0) (((~(a64) & UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64) & UINT64_C(0x0000FFFFFFFFFFFF)))) + +struct exp32_sig128 { int32_t exp; struct uint128 sig; }; +struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t, uint64_t); + +float128_t + softfloat_roundPackToF128(bool, int32_t, uint64_t, uint64_t, uint64_t, struct softfloat_status_t *); +float128_t + softfloat_normRoundPackToF128(bool, int32_t, uint64_t, uint64_t, struct softfloat_status_t *); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpu/softfloat3e/isNaN.cc b/src/cpu/softfloat3e/isNaN.cc new file mode 100644 index 0000000000..8c0bd19122 --- /dev/null +++ b/src/cpu/softfloat3e/isNaN.cc @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f16_isNaN(float16 a) +{ + return isNaNF16UI(a); +} + +bool f32_isNaN(float32 a) +{ + return isNaNF32UI(a); +} + +bool f64_isNaN(float64 a) +{ + return isNaNF64UI(a); +} + +bool extF80_isNaN(extFloat80_t a) +{ + return isNaNExtF80UI(a.signExp, a.signif); +} + +bool f128_isNaN(float128_t a) +{ + return isNaNF128UI(a.v64, a.v0); +} diff --git a/src/cpu/softfloat3e/isSignalingNaN.cc b/src/cpu/softfloat3e/isSignalingNaN.cc new file mode 100644 index 0000000000..994ac37841 --- /dev/null +++ b/src/cpu/softfloat3e/isSignalingNaN.cc @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bool f16_isSignalingNaN(float16 a) +{ + return softfloat_isSigNaNF16UI(a); +} + +bool f32_isSignalingNaN(float32 a) +{ + return softfloat_isSigNaNF32UI(a); +} + +bool f64_isSignalingNaN(float64 a) +{ + return softfloat_isSigNaNF64UI(a); +} + +bool extF80_isSignalingNaN(extFloat80_t a) +{ + return softfloat_isSigNaNExtF80UI(a.signExp, a.signif); +} + +bool f128_isSignalingNaN(float128_t a) +{ + return softfloat_isSigNaNF128UI(a.v64, a.v0); +} diff --git a/src/cpu/softfloat3e/opts-GCC.h b/src/cpu/softfloat3e/opts-GCC.h new file mode 100644 index 0000000000..dd6c0ab640 --- /dev/null +++ b/src/cpu/softfloat3e/opts-GCC.h @@ -0,0 +1,110 @@ + +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2017 The Regents of the University of California. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _OPTS_GCC_H_ +#define _OPTS_GCC_H_ + +#include +#include "primitiveTypes.h" + +#ifdef SOFTFLOAT_BUILTIN_CLZ + +static __inline uint8_t softfloat_countLeadingZeros16(uint16_t a) + { return a ? __builtin_clz(a) - 16 : 16; } +#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 + +static __inline uint8_t softfloat_countLeadingZeros32(uint32_t a) + { return a ? __builtin_clz(a) : 32; } +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 + +static __inline uint8_t softfloat_countLeadingZeros64(uint64_t a) + { return a ? __builtin_clzll(a) : 64; } +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 + +#endif + +#ifdef SOFTFLOAT_INTRINSIC_INT128 + +static __inline struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = (unsigned __int128) a * ((uint64_t) b<<32); + return uZ.s; +} +#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128 + +static __inline struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = (unsigned __int128) a * b; + return uZ.s; +} +#define softfloat_mul64To128 softfloat_mul64To128 + +static __inline +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) +{ + union { unsigned __int128 ui; struct uint128 s; } uZ; + uZ.ui = ((unsigned __int128) a64<<64 | a0) * b; + return uZ.s; +} +#define softfloat_mul128By32 softfloat_mul128By32 + +static __inline +void + softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr) +{ + unsigned __int128 z0, mid1, mid, z128; + z0 = (unsigned __int128) a0 * b0; + mid1 = (unsigned __int128) a64 * b0; + mid = mid1 + (unsigned __int128) a0 * b64; + z128 = (unsigned __int128) a64 * b64; + z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64; + mid <<= 64; + z0 += mid; + z128 += (z0 < mid); + zPtr[indexWord(4, 0)] = z0; + zPtr[indexWord(4, 1)] = z0>>64; + zPtr[indexWord(4, 2)] = z128; + zPtr[indexWord(4, 3)] = z128>>64; +} +#define softfloat_mul128To256M softfloat_mul128To256M + +#endif + +#endif + +#endif diff --git a/src/cpu/softfloat/softfloat_poly.cc b/src/cpu/softfloat3e/poly.cc similarity index 84% rename from src/cpu/softfloat/softfloat_poly.cc rename to src/cpu/softfloat3e/poly.cc index 5c7079353e..a89d7f03f8 100644 --- a/src/cpu/softfloat/softfloat_poly.cc +++ b/src/cpu/softfloat3e/poly.cc @@ -23,10 +23,10 @@ these four paragraphs for those parts of this code that are retained. * Stanislav Shwartsman [sshwarts at sourceforge net] * ==========================================================================*/ -#define FLOAT128 - #include + #include "softfloat.h" +#include "poly.h" // 2 3 4 n // f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x) @@ -39,13 +39,15 @@ these four paragraphs for those parts of this code that are retained. // f(x) ~ [ p(x) + x * q(x) ] // -float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status) { - float128 r = arr[--n]; + float128_t r = arr[--n]; do { - r = float128_mul(r, x, status); - r = float128_add(r, arr[--n], status); + r = f128_mulAdd(r, x, arr[--n], 0, status); +// r = f128_mul(r, x, &status); +// r = f128_add(r, arr[--n], &status); + } while (n > 0); return r; @@ -63,9 +65,9 @@ float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *statu // f(x) ~ [ p(x) + x * q(x) ] // -float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - return EvalPoly(float128_mul(x, x, status), arr, n, status); + return EvalPoly(f128_mul(x, x, &status), arr, n, &status); } // 3 5 7 9 2n+1 @@ -83,7 +85,7 @@ float128 EvenPoly(float128 x, float128 *arr, int n, struct float_status_t *statu // f(x) ~ x * [ p(x) + x * q(x) ] // -float128 OddPoly(float128 x, float128 *arr, int n, struct float_status_t *status) +float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status) { - return float128_mul(x, EvenPoly(x, arr, n, status), status); + return f128_mul(x, EvenPoly(x, arr, n, status), &status); } diff --git a/src/cpu/softfloat3e/poly.h b/src/cpu/softfloat3e/poly.h new file mode 100644 index 0000000000..1d6c3170c6 --- /dev/null +++ b/src/cpu/softfloat3e/poly.h @@ -0,0 +1,43 @@ +///////////////////////////////////////////////////////////////////////// +// $Id$ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2003-2018 Stanislav Shwartsman +// Written by Stanislav Shwartsman [sshwarts at sourceforge net] +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +///////////////////////////////////////////////////////////////////////// + +#ifndef _POLY_H_ +#define _POLY_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); +float128_t OddPoly(float128_t x, const float128_t *arr, int n, softfloat_status_t &status); +#else +float128_t EvenPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status); +float128_t OddPoly(float128_t x, const float128_t *arr, int n, struct float_status_t *status); +#endif // __cplusplus + +#ifdef __cplusplus +} +#endif + +#endif // _POLY_H_ diff --git a/src/cpu/softfloat3e/primitiveTypes.h b/src/cpu/softfloat3e/primitiveTypes.h new file mode 100644 index 0000000000..67751372f0 --- /dev/null +++ b/src/cpu/softfloat3e/primitiveTypes.h @@ -0,0 +1,54 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef primitiveTypes_h +#define primitiveTypes_h + +/*---------------------------------------------------------------------------- +| These macros are used to isolate the differences in word order between big- +| endian and little-endian platforms. +*----------------------------------------------------------------------------*/ +#define wordIncr 1 +#define indexWord(total, n) (n) +#define indexWordHi(total) ((total) - 1) +#define indexWordLo(total) 0 +#define indexMultiword(total, m, n) (n) +#define indexMultiwordHi(total, n) ((total) - (n)) +#define indexMultiwordLo(total, n) 0 +#define indexMultiwordHiBut(total, n) (n) +#define indexMultiwordLoBut(total, n) 0 +#define INIT_UINTM4(v3, v2, v1, v0) { v0, v1, v2, v3 } + +#endif diff --git a/src/cpu/softfloat3e/primitives.c b/src/cpu/softfloat3e/primitives.c new file mode 100644 index 0000000000..ba5afb76af --- /dev/null +++ b/src/cpu/softfloat3e/primitives.c @@ -0,0 +1,50 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include "primitives.h" + +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam128Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint8_t dist) +{ + uint8_t negDist = -dist; + struct uint128_extra z; + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(negDist & 63) | a0>>dist; + z.extra = a0<<(negDist & 63) | (extra != 0); + return z; +} diff --git a/src/cpu/softfloat3e/primitives.h b/src/cpu/softfloat3e/primitives.h new file mode 100644 index 0000000000..3c811838e7 --- /dev/null +++ b/src/cpu/softfloat3e/primitives.h @@ -0,0 +1,527 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _PRIMITIVES_H_ +#define _PRIMITIVES_H_ + +#include +#include +#include "softfloat_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SOFTFLOAT_FAST_DIV64TO32 + +#ifndef softfloat_shortShiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must be in +| the range 1 to 63. If any nonzero bits are shifted off, they are "jammed" +| into the least-significant bit of the shifted value by setting the least- +| significant bit to 1. This shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +static __inline +uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint8_t dist) +{ + return a>>dist | ((a & (((uint64_t) 1<>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +} +#endif + +#ifndef softfloat_shiftRightJam64 +/*---------------------------------------------------------------------------- +| Shifts 'a' right by the number of bits given in 'dist', which must not +| be zero. If any nonzero bits are shifted off, they are "jammed" into the +| least-significant bit of the shifted value by setting the least-significant +| bit to 1. This shifted-and-jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 64, the result will be either 0 or 1, depending on whether 'a' +| is zero or nonzero. +*----------------------------------------------------------------------------*/ +static __inline uint64_t softfloat_shiftRightJam64(uint64_t a, uint32_t dist) +{ + return (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +} +#endif + +/*---------------------------------------------------------------------------- +| A constant table that translates an 8-bit unsigned integer (the array index) +| into the number of leading 0 bits before the most-significant 1 of that +| integer. For integer zero (index 0), the corresponding table element is 8. +*----------------------------------------------------------------------------*/ +extern const uint_least8_t softfloat_countLeadingZeros8[256]; + +#ifndef softfloat_countLeadingZeros16 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 16 is returned. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_countLeadingZeros16(uint16_t a) +{ + uint8_t count = 8; + if (0x100 <= a) { + count = 0; + a >>= 8; + } + count += softfloat_countLeadingZeros8[a]; + return count; +} +#endif + +#ifndef softfloat_countLeadingZeros32 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 32 is returned. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_countLeadingZeros32(uint32_t a) +{ + uint8_t count = 0; + if (a < 0x10000) { + count = 16; + a <<= 16; + } + if (a < 0x1000000) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; +} +#endif + +#ifndef softfloat_countLeadingZeros64 +/*---------------------------------------------------------------------------- +| Returns the number of leading 0 bits before the most-significant 1 bit of +| 'a'. If 'a' is zero, 64 is returned. +*----------------------------------------------------------------------------*/ +uint8_t softfloat_countLeadingZeros64(uint64_t a); +#endif + +extern const uint16_t softfloat_approxRecip_1k0s[16]; +extern const uint16_t softfloat_approxRecip_1k1s[16]; + +#ifndef softfloat_approxRecip32_1 +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the number represented by 'a', +| where 'a' is interpreted as an unsigned fixed-point number with one integer +| bit and 31 fraction bits. The 'a' input must be "normalized", meaning that +| its most-significant bit (bit 31) must be 1. Thus, if A is the value of +| the fixed-point interpretation of 'a', then 1 <= A < 2. The returned value +| is interpreted as a pure unsigned fraction, having no integer bits and 32 +| fraction bits. The approximation returned is never greater than the true +| reciprocal 1/A, and it differs from the true reciprocal by at most 2.006 ulp +| (units in the last place). +*----------------------------------------------------------------------------*/ +#ifdef SOFTFLOAT_FAST_DIV64TO32 +#define softfloat_approxRecip32_1(a) ((uint32_t) (UINT64_C(0x7FFFFFFFFFFFFFFF) / (uint32_t) (a))) +#endif +#endif + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[16]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[16]; + +/*---------------------------------------------------------------------------- +| Returns an approximation to the reciprocal of the square root of the number +| represented by 'a', where 'a' is interpreted as an unsigned fixed-point +| number either with one integer bit and 31 fraction bits or with two integer +| bits and 30 fraction bits. The format of 'a' is determined by 'oddExpA', +| which must be either 0 or 1. If 'oddExpA' is 1, 'a' is interpreted as +| having one integer bit, and if 'oddExpA' is 0, 'a' is interpreted as having +| two integer bits. The 'a' input must be "normalized", meaning that its +| most-significant bit (bit 31) must be 1. Thus, if A is the value of the +| fixed-point interpretation of 'a', it follows that 1 <= A < 2 when 'oddExpA' +| is 1, and 2 <= A < 4 when 'oddExpA' is 0. +| The returned value is interpreted as a pure unsigned fraction, having +| no integer bits and 32 fraction bits. The approximation returned is never +| greater than the true reciprocal 1/sqrt(A), and it differs from the true +| reciprocal by at most 2.06 ulp (units in the last place). The approximation +| returned is also always within the range 0.5 to 1; thus, the most- +| significant bit of the result is always set. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a); + +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is equal to the 128-bit unsigned integer formed by concatenating +| 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +static __inline +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 == b64) && (a0 == b0); +} + +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is less than or equal to the 128-bit unsigned integer formed by +| concatenating 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +static __inline +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); +} + +/*---------------------------------------------------------------------------- +| Returns true if the 128-bit unsigned integer formed by concatenating 'a64' +| and 'a0' is less than the 128-bit unsigned integer formed by concatenating +| 'b64' and 'b0'. +*----------------------------------------------------------------------------*/ +static __inline +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 < b0)); +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' left by the +| number of bits given in 'dist', which must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + struct uint128 z; + z.v64 = a64<>(-dist & 63); + z.v0 = a0<>dist; + z.v0 = a64<<(-dist & 63) | a0>>dist; + return z; +} + +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam64Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +static __inline +struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint8_t dist) +{ + struct uint64_extra z; + z.v = a>>dist; + z.extra = a<<(-dist & 63) | (extra != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the +| number of bits given in 'dist', which must be in the range 1 to 63. If any +| nonzero bits are shifted off, they are "jammed" into the least-significant +| bit of the shifted value by setting the least-significant bit to 1. This +| shifted-and-jammed value is returned. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + uint8_t negDist = -dist; + struct uint128 z; + z.v64 = a64>>dist; + z.v0 = + a64<<(negDist & 63) | a0>>dist + | ((uint64_t) (a0<<(negDist & 63)) != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| This function is the same as 'softfloat_shiftRightJam128Extra' (below), +| except that 'dist' must be in the range 1 to 63. +*----------------------------------------------------------------------------*/ +extern struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint8_t dist); + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a' and 'extra' right by 64 +| _plus_ the number of bits given in 'dist', which must not be zero. This +| shifted value is at most 64 nonzero bits and is returned in the 'v' field +| of the 'struct uint64_extra' result. The 64-bit 'extra' field of the result +| contains a value formed as follows from the bits that were shifted off: The +| _last_ bit shifted off is the most-significant bit of the 'extra' field, and +| the other 63 bits of the 'extra' field are all zero if and only if _all_but_ +| _the_last_ bits shifted off were all zero. +| (This function makes more sense if 'a' and 'extra' are considered to form +| an unsigned fixed-point number with binary point between 'a' and 'extra'. +| This fixed-point value is shifted right by the number of bits given in +| 'dist', and the integer part of this shifted value is returned in the 'v' +| field of the result. The fractional part of the shifted value is modified +| as described above and returned in the 'extra' field of the result.) +*----------------------------------------------------------------------------*/ +static __inline +struct uint64_extra + softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint32_t dist) +{ + struct uint64_extra z; + if (dist < 64) { + z.v = a>>dist; + z.extra = a<<(-dist & 63); + } else { + z.v = 0; + z.extra = (dist == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 128 bits formed by concatenating 'a64' and 'a0' right by the +| number of bits given in 'dist', which must not be zero. If any nonzero bits +| are shifted off, they are "jammed" into the least-significant bit of the +| shifted value by setting the least-significant bit to 1. This shifted-and- +| jammed value is returned. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is +| greater than 128, the result will be either 0 or 1, depending on whether the +| original 128 bits are all zeros. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 + softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128 z; + + if (dist < 64) { + u8NegDist = -dist; + z.v64 = a64>>dist; + z.v0 = + a64<<(u8NegDist & 63) | a0>>dist + | ((uint64_t) (a0<<(u8NegDist & 63)) != 0); + } else { + z.v64 = 0; + z.v0 = + (dist < 127) + ? a64>>(dist & 63) + | (((a64 & (((uint64_t) 1<<(dist & 63)) - 1)) | a0) + != 0) + : ((a64 | a0) != 0); + } + return z; +} + +/*---------------------------------------------------------------------------- +| Shifts the 192 bits formed by concatenating 'a64', 'a0', and 'extra' right +| by 64 _plus_ the number of bits given in 'dist', which must not be zero. +| This shifted value is at most 128 nonzero bits and is returned in the 'v' +| field of the 'struct uint128_extra' result. The 64-bit 'extra' field of the +| result contains a value formed as follows from the bits that were shifted +| off: The _last_ bit shifted off is the most-significant bit of the 'extra' +| field, and the other 63 bits of the 'extra' field are all zero if and only +| if _all_but_the_last_ bits shifted off were all zero. +| (This function makes more sense if 'a64', 'a0', and 'extra' are considered +| to form an unsigned fixed-point number with binary point between 'a0' and +| 'extra'. This fixed-point value is shifted right by the number of bits +| given in 'dist', and the integer part of this shifted value is returned +| in the 'v' field of the result. The fractional part of the shifted value +| is modified as described above and returned in the 'extra' field of the +| result.) +*----------------------------------------------------------------------------*/ +static __inline +struct uint128_extra + softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128_extra z; + + u8NegDist = -dist; + if (dist < 64) { + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist; + z.extra = a0<<(u8NegDist & 63); + } else { + z.v.v64 = 0; + if (dist == 64) { + z.v.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if (dist < 128) { + z.v.v0 = a64>>(dist & 63); + z.extra = a64<<(u8NegDist & 63); + } else { + z.v.v0 = 0; + z.extra = (dist == 128) ? a64 : (a64 != 0); + } + } + } + z.extra |= (extra != 0); + return z; + +} + +/*---------------------------------------------------------------------------- +| Shifts the 256-bit unsigned integer pointed to by 'aPtr' right by the number +| of bits given in 'dist', which must not be zero. If any nonzero bits are +| shifted off, they are "jammed" into the least-significant bit of the shifted +| value by setting the least-significant bit to 1. This shifted-and-jammed +| value is stored at the location pointed to by 'zPtr'. Each of 'aPtr' and +| 'zPtr' points to an array of four 64-bit elements that concatenate in the +| platform's normal endian order to form a 256-bit integer. +| The value of 'dist' can be arbitrarily large. In particular, if 'dist' +| is greater than 256, the stored result will be either 0 or 1, depending on +| whether the original 256 bits are all zeros. +*----------------------------------------------------------------------------*/ +void + softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *zPtr); + +#ifndef softfloat_add128 +/*---------------------------------------------------------------------------- +| Returns the sum of the 128-bit integer formed by concatenating 'a64' and +| 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. The +| addition is modulo 2^128, so any carry out is lost. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; +} +#endif + +#ifndef softfloat_add256M +/*---------------------------------------------------------------------------- +| Adds the two 256-bit integers pointed to by 'aPtr' and 'bPtr'. The addition +| is modulo 2^256, so any carry out is lost. The sum is stored at the +| location pointed to by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to +| an array of four 64-bit elements that concatenate in the platform's normal +| endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_add256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr); +#endif + +#ifndef softfloat_sub128 +/*---------------------------------------------------------------------------- +| Returns the difference of the 128-bit integer formed by concatenating 'a64' +| and 'a0' and the 128-bit integer formed by concatenating 'b64' and 'b0'. +| The subtraction is modulo 2^128, so any borrow out (carry out) is lost. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + z.v0 = a0 - b0; + z.v64 = a64 - b64; + z.v64 -= (a0 < b0); + return z; +} +#endif + +#ifndef softfloat_sub256M +/*---------------------------------------------------------------------------- +| Subtracts the 256-bit integer pointed to by 'bPtr' from the 256-bit integer +| pointed to by 'aPtr'. The addition is modulo 2^256, so any borrow out +| (carry out) is lost. The difference is stored at the location pointed to +| by 'zPtr'. Each of 'aPtr', 'bPtr', and 'zPtr' points to an array of four +| 64-bit elements that concatenate in the platform's normal endian order to +| form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_sub256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr); +#endif + +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of 'a', 'b', and 2^32. +*----------------------------------------------------------------------------*/ +static __inline struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) +{ + uint64_t mid; + struct uint128 z; + mid = (uint64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; +} + +/*---------------------------------------------------------------------------- +| Returns the 128-bit product of 'a' and 'b'. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b); + +/*---------------------------------------------------------------------------- +| Returns the product of the 128-bit integer formed by concatenating 'a64' and +| 'a0', multiplied by 'b'. The multiplication is modulo 2^128; any overflow +| bits are discarded. +*----------------------------------------------------------------------------*/ +static __inline +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) +{ + struct uint128 z; + uint64_t mid; + uint32_t carry; + z.v0 = a0 * b; + mid = (uint64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint32_t) (z.v0>>32) - (uint32_t) mid); + z.v64 = a64 * b + (uint32_t) ((mid + carry)>>32); + return z; +} + +/*---------------------------------------------------------------------------- +| Multiplies the 128-bit unsigned integer formed by concatenating 'a64' and +| 'a0' by the 128-bit unsigned integer formed by concatenating 'b64' and +| 'b0'. The 256-bit product is stored at the location pointed to by 'zPtr'. +| Argument 'zPtr' points to an array of four 64-bit elements that concatenate +| in the platform's normal endian order to form a 256-bit integer. +*----------------------------------------------------------------------------*/ +void + softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr); +#ifdef __cplusplus +} +#endif + +#endif // _PRIMITIVES_H_ diff --git a/src/cpu/softfloat3e/s_add128.cc b/src/cpu/softfloat3e/s_add128.cc new file mode 100644 index 0000000000..8efabb8501 --- /dev/null +++ b/src/cpu/softfloat3e/s_add128.cc @@ -0,0 +1,51 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_add128 + +struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + + z.v0 = a0 + b0; + z.v64 = a64 + b64 + (z.v0 < a0); + return z; +} + +#endif + diff --git a/src/cpu/softfloat3e/s_add256M.c b/src/cpu/softfloat3e/s_add256M.c new file mode 100644 index 0000000000..32fdf122f5 --- /dev/null +++ b/src/cpu/softfloat3e/s_add256M.c @@ -0,0 +1,60 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitiveTypes.h" + +#ifndef softfloat_add256M + +void softfloat_add256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr) +{ + unsigned int index; + uint8_t carry; + uint64_t wordA, wordZ; + + index = indexWordLo(4); + carry = 0; + for (;;) { + wordA = aPtr[index]; + wordZ = wordA + bPtr[index] + carry; + zPtr[index] = wordZ; + if (index == indexWordHi(4)) break; + if (wordZ != wordA) carry = (wordZ < wordA); + index += wordIncr; + } +} + +#endif + diff --git a/src/cpu/softfloat3e/s_addMagsExtF80.cc b/src/cpu/softfloat3e/s_addMagsExtF80.cc new file mode 100644 index 0000000000..5cc969198b --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsExtF80.cc @@ -0,0 +1,146 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t softfloat_addMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) +{ + int32_t expA; + uint64_t sigA; + int32_t expB; + uint64_t sigB; + int32_t expDiff; + uint64_t sigZ, sigZExtra; + struct exp32_sig64 normExpSig; + int32_t expZ; + struct uint64_extra sig64Extra; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64(uiA64); + sigA = uiA0; + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA << 1) || ((expB == 0x7FFF) && (sigB << 1))) + goto propagateNaN; + if (sigB && ! expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80_twoargs(uiA64, uiA0); + } + if (expB == 0x7FFF) { + if (sigB << 1) goto propagateNaN; + if (sigA && ! expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (! expB && sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + expZ = expB; + sigZ = sigB; + sigZExtra = 0; + goto roundAndPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expB == 0) { + if (sigB == 0) { + expZ = expA; + sigZ = sigA; + sigZExtra = 0; + goto roundAndPack; + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + sigZ = sigA + sigB; + sigZExtra = 0; + expZ = expA; + goto shiftRight1; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expDiff < 0) { + expZ = expB; + sig64Extra = softfloat_shiftRightJam64Extra(sigA, 0, -expDiff); + sigA = sig64Extra.v; + sigZExtra = sig64Extra.extra; + } else { + expZ = expA; + sig64Extra = softfloat_shiftRightJam64Extra(sigB, 0, expDiff); + sigB = sig64Extra.v; + sigZExtra = sig64Extra.extra; + } + sigZ = sigA + sigB; + if (sigZ & UINT64_C(0x8000000000000000)) goto roundAndPack; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + shiftRight1: + sig64Extra = softfloat_shortShiftRightJam64Extra(sigZ, sigZExtra, 1); + sigZ = sig64Extra.v | UINT64_C(0x8000000000000000); + sigZExtra = sig64Extra.extra; + ++expZ; + roundAndPack: + return softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); +} diff --git a/src/cpu/softfloat3e/s_addMagsF128.cc b/src/cpu/softfloat3e/s_addMagsF128.cc new file mode 100644 index 0000000000..b831796cc4 --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF128.cc @@ -0,0 +1,138 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" + +float128_t softfloat_addMagsF128(uint64_t uiA64, uint64_t uiA0, uint64_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) +{ + int32_t expA; + struct uint128 sigA; + int32_t expB; + struct uint128 sigB; + int32_t expDiff; + struct uint128 uiZ, sigZ; + int32_t expZ; + uint64_t sigZExtra; + struct uint128_extra sig128Extra; + + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + expDiff = expA - expB; + if (! expDiff) { + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + return uiZ; + } + sigZ = softfloat_add128(sigA.v64, sigA.v0, sigB.v64, sigB.v0); + if (! expA) { + uiZ.v64 = packToF128UI64(signZ, 0, sigZ.v64); + uiZ.v0 = sigZ.v0; + return uiZ; + } + expZ = expA; + sigZ.v64 |= UINT64_C(0x0002000000000000); + sigZExtra = 0; + goto shiftRight1; + } + if (expDiff < 0) { + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + } + expZ = expB; + if (expA) { + sigA.v64 |= UINT64_C(0x0001000000000000); + } else { + ++expDiff; + sigZExtra = 0; + if (! expDiff) goto newlyAligned; + } + sig128Extra = + softfloat_shiftRightJam128Extra(sigA.v64, sigA.v0, 0, -expDiff); + sigA = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } else { + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + return uiZ; + } + expZ = expA; + if (expB) { + sigB.v64 |= UINT64_C(0x0001000000000000); + } else { + --expDiff; + sigZExtra = 0; + if (! expDiff) goto newlyAligned; + } + sig128Extra = softfloat_shiftRightJam128Extra(sigB.v64, sigB.v0, 0, expDiff); + sigB = sig128Extra.v; + sigZExtra = sig128Extra.extra; + } + newlyAligned: + sigZ = + softfloat_add128( + sigA.v64 | UINT64_C(0x0001000000000000), + sigA.v0, + sigB.v64, + sigB.v0 + ); + --expZ; + if (sigZ.v64 < UINT64_C(0x0002000000000000)) goto roundAndPack; + ++expZ; + shiftRight1: + sig128Extra = softfloat_shortShiftRightJam128Extra(sigZ.v64, sigZ.v0, sigZExtra, 1); + sigZ = sig128Extra.v; + sigZExtra = sig128Extra.extra; + roundAndPack: + return + softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status); + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; +} diff --git a/src/cpu/softfloat3e/s_addMagsF16.c b/src/cpu/softfloat3e/s_addMagsF16.c new file mode 100644 index 0000000000..022f254a80 --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF16.c @@ -0,0 +1,192 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float16 softfloat_addMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +{ + int8_t expA; + uint16_t sigA; + int8_t expB; + uint16_t sigB; + int8_t expDiff; + uint16_t uiZ; + bool signZ; + int8_t expZ; + uint16_t sigZ; + uint16_t sigX, sigY; + int8_t shiftDist; + uint32_t sig32Z; + int8_t roundingMode; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + signZ = signF16UI(uiA); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + uiA = packToF16UI(signZ, 0, 0); + } + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! expA) { + uiZ = uiA + sigB; + if (sigA | sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + bool isTiny = (expF16UI(uiZ) == 0); + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF16UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } + return uiZ; + } + if (expA == 0x1F) { + if (sigA | sigB) goto propagateNaN; + return uiA; + } + expZ = expA; + sigZ = 0x0800 + sigA + sigB; + if (! (sigZ & 1) && (expZ < 0x1E)) { + sigZ >>= 1; + goto pack; + } + sigZ <<= 3; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expDiff < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + if (expB == 0x1F) { + if (sigB) goto propagateNaN; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToF16UI(signZ, 0x1F, 0); + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + if (expDiff <= -13) { + uiZ = packToF16UI(signZ, expB, sigB); + if (expA | sigA) goto addEpsilon; + return uiZ; + } + expZ = expB; + sigX = sigB | 0x0400; + sigY = sigA + (expA ? 0x0400 : sigA); + shiftDist = 19 + expDiff; + } else { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + uiZ = uiA; + if (expA == 0x1F) { + if (sigA) goto propagateNaN; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiZ; + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + if (13 <= expDiff) { + if (expB | sigB) goto addEpsilon; + return uiZ; + } + expZ = expA; + sigX = sigA | 0x0400; + sigY = sigB + (expB ? 0x0400 : sigB); + shiftDist = 19 - expDiff; + } + sig32Z = ((uint32_t) sigX<<19) + ((uint32_t) sigY<>16; + if (sig32Z & 0xFFFF) { + sigZ |= 1; + } else { + if (! (sigZ & 0xF) && (expZ < 0x1E)) { + sigZ >>= 4; + goto pack; + } + } + } + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(uiA, uiB, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + addEpsilon: + roundingMode = softfloat_getRoundingMode(status); + if (roundingMode != softfloat_round_near_even) { + if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) { + ++uiZ; + if ((uint16_t) (uiZ<<1) == 0xF800) { + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + } + } + } + softfloat_raiseFlags(status, softfloat_flag_inexact); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + pack: + return packToF16UI(signZ, expZ, sigZ); +} diff --git a/src/cpu/softfloat3e/s_addMagsF32.c b/src/cpu/softfloat3e/s_addMagsF32.c new file mode 100644 index 0000000000..df902348a4 --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF32.c @@ -0,0 +1,147 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" + +float32 softfloat_addMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +{ + int16_t expA; + uint32_t sigA; + int16_t expB; + uint32_t sigB; + int16_t expDiff; + uint32_t uiZ; + bool signZ; + int16_t expZ; + uint32_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + signZ = signF32UI(uiA); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + uiA = packToF32UI(signZ, 0, 0); + } + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! expA) { + uiZ = uiA + sigB; + if (sigA | sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + bool isTiny = (expF32UI(uiZ) == 0); + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } + return uiZ; + } + if (expA == 0xFF) { + if (sigA | sigB) goto propagateNaN; + return uiA; + } + expZ = expA; + sigZ = 0x01000000 + sigA + sigB; + if (! (sigZ & 1) && (expZ < 0xFE)) { + return packToF32UI(signZ, expZ, sigZ>>1); + } + sigZ <<= 6; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + signZ = signF32UI(uiA); + sigA <<= 6; + sigB <<= 6; + if (expDiff < 0) { + if (expB == 0xFF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToF32UI(signZ, 0xFF, 0); + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expB; + sigA += expA ? 0x20000000 : sigA; + sigA = softfloat_shiftRightJam32(sigA, -expDiff); + } else { + if (expA == 0xFF) { + if (sigA) goto propagateNaN; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiA; + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expA; + sigB += expB ? 0x20000000 : sigB; + sigB = softfloat_shiftRightJam32(sigB, expDiff); + } + sigZ = 0x20000000 + sigA + sigB; + if (sigZ < 0x40000000) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF32(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF32UI(uiA, uiB, status); +} diff --git a/src/cpu/softfloat3e/s_addMagsF64.c b/src/cpu/softfloat3e/s_addMagsF64.c new file mode 100644 index 0000000000..a315860f6c --- /dev/null +++ b/src/cpu/softfloat3e/s_addMagsF64.c @@ -0,0 +1,149 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" + +float64 softfloat_addMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) +{ + int16_t expA; + uint64_t sigA; + int16_t expB; + uint64_t sigB; + int16_t expDiff; + uint64_t uiZ; + int16_t expZ; + uint64_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) { + sigA = 0; + uiA = packToF64UI(signZ, 0, 0); + } + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (! expA) { + uiZ = uiA + sigB; + if (sigA | sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + bool isTiny = (expF64UI(uiZ) == 0); + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } + return uiZ; + } + if (expA == 0x7FF) { + if (sigA | sigB) goto propagateNaN; + return uiA; + } + expZ = expA; + sigZ = UINT64_C(0x0020000000000000) + sigA + sigB; + sigZ <<= 9; + } else { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + sigA <<= 9; + sigB <<= 9; + if (expDiff < 0) { + if (expB == 0x7FF) { + if (sigB) goto propagateNaN; + if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToF64UI(signZ, 0x7FF, 0); + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expB; + if (expA) { + sigA += UINT64_C(0x2000000000000000); + } else { + sigA <<= 1; + } + sigA = softfloat_shiftRightJam64(sigA, -expDiff); + } else { + if (expA == 0x7FF) { + if (sigA) goto propagateNaN; + if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal); + return uiA; + } + + if ((!expA && sigA) || (!expB && sigB)) + softfloat_raiseFlags(status, softfloat_flag_denormal); + + expZ = expA; + if (expB) { + sigB += UINT64_C(0x2000000000000000); + } else { + sigB <<= 1; + } + sigB = softfloat_shiftRightJam64(sigB, expDiff); + } + sigZ = UINT64_C(0x2000000000000000) + sigA + sigB; + if (sigZ < UINT64_C(0x4000000000000000)) { + --expZ; + sigZ <<= 1; + } + } + return softfloat_roundPackToF64(signZ, expZ, sigZ, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF64UI(uiA, uiB, status); +} diff --git a/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c b/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c new file mode 100644 index 0000000000..776c146ef3 --- /dev/null +++ b/src/cpu/softfloat3e/s_approxRecipSqrt32_1.c @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; +extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; + +uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a) +{ + int index; + uint16_t eps, r0; + uint32_t ESqrR0; + uint32_t sigma0; + uint32_t r; + uint32_t sqrSigma0; + + index = (a>>27 & 0xE) + oddExpA; + eps = (uint16_t) (a>>12); + r0 = softfloat_approxRecipSqrt_1k0s[index] - ((softfloat_approxRecipSqrt_1k1s[index] * (uint32_t) eps) >>20); + ESqrR0 = (uint32_t) r0 * r0; + if (! oddExpA) ESqrR0 <<= 1; + sigma0 = ~(uint32_t) (((uint32_t) ESqrR0 * (uint64_t) a)>>23); + r = ((uint32_t) r0<<16) + ((r0 * (uint64_t) sigma0)>>25); + sqrSigma0 = ((uint64_t) sigma0 * sigma0)>>32; + r += ((uint32_t) ((r>>1) + (r>>3) - ((uint32_t) r0<<14)) * (uint64_t) sqrSigma0) >>48; + if (! (r & 0x80000000)) r = 0x80000000; + return r; +} + diff --git a/src/cpu/softfloat3e/s_approxRecipSqrt_1Ks.c b/src/cpu/softfloat3e/s_approxRecipSqrt_1Ks.c new file mode 100644 index 0000000000..56965c541e --- /dev/null +++ b/src/cpu/softfloat3e/s_approxRecipSqrt_1Ks.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +const uint16_t softfloat_approxRecipSqrt_1k0s[16] = { + 0xB4C9, 0xFFAB, 0xAA7D, 0xF11C, 0xA1C5, 0xE4C7, 0x9A43, 0xDA29, + 0x93B5, 0xD0E5, 0x8DED, 0xC8B7, 0x88C6, 0xC16D, 0x8424, 0xBAE1 +}; +const uint16_t softfloat_approxRecipSqrt_1k1s[16] = { + 0xA5A5, 0xEA42, 0x8C21, 0xC62D, 0x788F, 0xAA7F, 0x6928, 0x94B6, + 0x5CC7, 0x8335, 0x52A6, 0x74E2, 0x4A3E, 0x68FE, 0x432B, 0x5EFD +}; diff --git a/src/cpu/softfloat3e/s_approxRecip_1Ks.c b/src/cpu/softfloat3e/s_approxRecip_1Ks.c new file mode 100644 index 0000000000..aadcd235ca --- /dev/null +++ b/src/cpu/softfloat3e/s_approxRecip_1Ks.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +const uint16_t softfloat_approxRecip_1k0s[16] = { + 0xFFC4, 0xF0BE, 0xE363, 0xD76F, 0xCCAD, 0xC2F0, 0xBA16, 0xB201, + 0xAA97, 0xA3C6, 0x9D7A, 0x97A6, 0x923C, 0x8D32, 0x887E, 0x8417 +}; +const uint16_t softfloat_approxRecip_1k1s[16] = { + 0xF0F1, 0xD62C, 0xBFA1, 0xAC77, 0x9C0A, 0x8DDB, 0x8185, 0x76BA, + 0x6D3B, 0x64D4, 0x5D5C, 0x56B1, 0x50B6, 0x4B55, 0x4679, 0x4211 +}; diff --git a/src/cpu/softfloat3e/s_commonNaNToExtF80UI.cc b/src/cpu/softfloat3e/s_commonNaNToExtF80UI.cc new file mode 100644 index 0000000000..7afca62704 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToExtF80UI.cc @@ -0,0 +1,69 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN *aPtr) +{ + struct uint128 uiZ; + + uiZ.v64 = (uint16_t) aPtr->sign<<15 | 0x7FFF; + uiZ.v0 = UINT64_C(0xC000000000000000) | aPtr->v64>>1; + return uiZ; +} + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_extF80UIToCommonNaN(uint16_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNExtF80UI(uiA64, uiA0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA64>>15; + zPtr->v64 = uiA0<<1; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF128UI.cc b/src/cpu/softfloat3e/s_commonNaNToF128UI.cc new file mode 100644 index 0000000000..a0bb93dd39 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF128UI.cc @@ -0,0 +1,72 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN *aPtr) +{ + struct uint128 uiZ; + + uiZ = softfloat_shortShiftRight128(aPtr->v64, aPtr->v0, 16); + uiZ.v64 |= (uint64_t) aPtr->sign<<63 | UINT64_C(0x7FFF800000000000); + return uiZ; +} + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void + softfloat_f128UIToCommonNaN(uint64_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + struct uint128 NaNSig; + + if (softfloat_isSigNaNF128UI(uiA64, uiA0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + NaNSig = softfloat_shortShiftLeft128(uiA64, uiA0, 16); + zPtr->sign = uiA64>>63; + zPtr->v64 = NaNSig.v64; + zPtr->v0 = NaNSig.v0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF16UI.c b/src/cpu/softfloat3e/s_commonNaNToF16UI.c new file mode 100644 index 0000000000..20da6a04fb --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF16UI.c @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint16_t softfloat_commonNaNToF16UI(const struct commonNaN *aPtr) +{ + return (uint16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54; +} + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f16UIToCommonNaN(uint16_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNF16UI(uiA)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA>>15; + zPtr->v64 = (uint64_t) uiA<<54; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF32UI.c b/src/cpu/softfloat3e/s_commonNaNToF32UI.c new file mode 100644 index 0000000000..866ebb8f85 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF32UI.c @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_commonNaNToF32UI(const struct commonNaN *aPtr) +{ + return (uint32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41; +} + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN(uint32_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNF32UI(uiA)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA>>31; + zPtr->v64 = (uint64_t) uiA<<41; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_commonNaNToF64UI.c b/src/cpu/softfloat3e/s_commonNaNToF64UI.c new file mode 100644 index 0000000000..8e73f68f49 --- /dev/null +++ b/src/cpu/softfloat3e/s_commonNaNToF64UI.c @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "specialize.h" + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_commonNaNToF64UI(const struct commonNaN *aPtr) +{ + return (uint64_t) aPtr->sign<<63 | UINT64_C(0x7FF8000000000000) | aPtr->v64>>12; +} + +/*---------------------------------------------------------------------------- +| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN(uint64_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status) +{ + if (softfloat_isSigNaNF64UI(uiA)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + } + zPtr->sign = uiA>>63; + zPtr->v64 = uiA<<12; + zPtr->v0 = 0; +} diff --git a/src/cpu/softfloat3e/s_countLeadingZeros16.c b/src/cpu/softfloat3e/s_countLeadingZeros16.c new file mode 100644 index 0000000000..ffbb9c943d --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros16.c @@ -0,0 +1,56 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_countLeadingZeros16 + +#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 +#include "primitives.h" + +uint8_t softfloat_countLeadingZeros16(uint16_t a) +{ + uint8_t count; + + count = 8; + if (0x100 <= a) { + count = 0; + a >>= 8; + } + count += softfloat_countLeadingZeros8[a]; + return count; +} + +#endif diff --git a/src/cpu/softfloat3e/s_countLeadingZeros32.c b/src/cpu/softfloat3e/s_countLeadingZeros32.c new file mode 100644 index 0000000000..3f594137f7 --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros32.c @@ -0,0 +1,61 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_countLeadingZeros32 + +#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 +#include "primitives.h" + +uint8_t softfloat_countLeadingZeros32(uint32_t a) +{ + uint8_t count; + + count = 0; + if (a < 0x10000) { + count = 16; + a <<= 16; + } + if (a < 0x1000000) { + count += 8; + a <<= 8; + } + count += softfloat_countLeadingZeros8[a>>24]; + return count; +} + +#endif diff --git a/src/cpu/softfloat3e/s_countLeadingZeros64.c b/src/cpu/softfloat3e/s_countLeadingZeros64.c new file mode 100644 index 0000000000..c96c4ec8c7 --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros64.c @@ -0,0 +1,70 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_countLeadingZeros64 + +#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64 +#include "primitives.h" + +uint8_t softfloat_countLeadingZeros64(uint64_t a) +{ + uint8_t count; + uint32_t a32; + + count = 0; + a32 = a>>32; + if (! a32) { + count = 32; + a32 = a; + } + /*------------------------------------------------------------------------ + | From here, result is current count + count leading zeros of `a32'. + *------------------------------------------------------------------------*/ + if (a32 < 0x10000) { + count += 16; + a32 <<= 16; + } + if (a32 < 0x1000000) { + count += 8; + a32 <<= 8; + } + count += softfloat_countLeadingZeros8[a32>>24]; + return count; +} + +#endif diff --git a/src/cpu/softfloat3e/s_countLeadingZeros8.c b/src/cpu/softfloat3e/s_countLeadingZeros8.c new file mode 100644 index 0000000000..873ab81efc --- /dev/null +++ b/src/cpu/softfloat3e/s_countLeadingZeros8.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitives.h" + +const uint_least8_t softfloat_countLeadingZeros8[256] = { + 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 +}; + diff --git a/src/cpu/softfloat3e/s_eq128.c b/src/cpu/softfloat3e/s_eq128.c new file mode 100644 index 0000000000..45495dd922 --- /dev/null +++ b/src/cpu/softfloat3e/s_eq128.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +#ifndef softfloat_eq128 + +bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 == b64) && (a0 == b0); +} + +#endif diff --git a/src/cpu/softfloat3e/s_le128.c b/src/cpu/softfloat3e/s_le128.c new file mode 100644 index 0000000000..d299b5e92b --- /dev/null +++ b/src/cpu/softfloat3e/s_le128.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +#ifndef softfloat_le128 + +bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); +} + +#endif diff --git a/src/cpu/softfloat3e/s_lt128.c b/src/cpu/softfloat3e/s_lt128.c new file mode 100644 index 0000000000..225c233564 --- /dev/null +++ b/src/cpu/softfloat3e/s_lt128.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include + +#ifndef softfloat_lt128 + +bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + return (a64 < b64) || ((a64 == b64) && (a0 < b0)); +} + +#endif diff --git a/src/cpu/softfloat3e/s_mul128By32.cc b/src/cpu/softfloat3e/s_mul128By32.cc new file mode 100644 index 0000000000..920ad57330 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul128By32.cc @@ -0,0 +1,54 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_mul128By32 + +struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) +{ + struct uint128 z; + uint64_t mid; + uint32_t carry; + + z.v0 = a0 * b; + mid = (uint64_t) (uint32_t) (a0>>32) * b; + carry = (uint32_t) ((uint32_t) (z.v0>>32) - (uint32_t) mid); + z.v64 = a64 * b + (uint32_t) ((mid + carry)>>32); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_mul128To256M.cc b/src/cpu/softfloat3e/s_mul128To256M.cc new file mode 100644 index 0000000000..04b25a5755 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul128To256M.cc @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#include "primitives.h" +#include "primitiveTypes.h" + +void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr) +{ + struct uint128 p0, p64, p128; + uint64_t z64, z128, z192; + + p0 = softfloat_mul64To128(a0, b0); + zPtr[indexWord(4, 0)] = p0.v0; + p64 = softfloat_mul64To128(a64, b0); + z64 = p64.v0 + p0.v64; + z128 = p64.v64 + (z64 < p64.v0); + p128 = softfloat_mul64To128(a64, b64); + z128 += p128.v0; + z192 = p128.v64 + (z128 < p128.v0); + p64 = softfloat_mul64To128(a0, b64); + z64 += p64.v0; + zPtr[indexWord(4, 1)] = z64; + p64.v64 += (z64 < p64.v0); + z128 += p64.v64; + zPtr[indexWord(4, 2)] = z128; + zPtr[indexWord(4, 3)] = z192 + (z128 < p64.v64); +} + diff --git a/src/cpu/softfloat3e/s_mul64ByShifted32To128.cc b/src/cpu/softfloat3e/s_mul64ByShifted32To128.cc new file mode 100644 index 0000000000..90938ac797 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul64ByShifted32To128.cc @@ -0,0 +1,52 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_mul64ByShifted32To128 + +struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) +{ + uint64_t mid; + struct uint128 z; + + mid = (uint64_t) (uint32_t) a * b; + z.v0 = mid<<32; + z.v64 = (uint64_t) (uint32_t) (a>>32) * b + (mid>>32); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_mul64To128.cc b/src/cpu/softfloat3e/s_mul64To128.cc new file mode 100644 index 0000000000..d1ab9296a3 --- /dev/null +++ b/src/cpu/softfloat3e/s_mul64To128.cc @@ -0,0 +1,63 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" +#include "primitives.h" + +#ifndef softfloat_mul64To128 + +struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) +{ + uint32_t a32, a0, b32, b0; + struct uint128 z; + uint64_t mid1, mid; + + a32 = a>>32; + a0 = a; + b32 = b>>32; + b0 = b; + z.v0 = (uint64_t) a0 * b0; + mid1 = (uint64_t) a32 * b0; + mid = mid1 + (uint64_t) a0 * b32; + z.v64 = (uint64_t) a32 * b32; + z.v64 += (uint64_t) (mid < mid1)<<32 | mid>>32; + mid <<= 32; + z.v0 += mid; + z.v64 += (z.v0 < mid); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_normRoundPackToExtF80.cc b/src/cpu/softfloat3e/s_normRoundPackToExtF80.cc new file mode 100644 index 0000000000..753f761849 --- /dev/null +++ b/src/cpu/softfloat3e/s_normRoundPackToExtF80.cc @@ -0,0 +1,62 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" + +extFloat80_t softfloat_normRoundPackToExtF80(bool sign, int32_t exp, + uint64_t sig, + uint64_t sigExtra, + uint8_t roundingPrecision, + struct softfloat_status_t *status) +{ + int8_t shiftDist; + struct uint128 sig128; + + if (! sig) { + exp -= 64; + sig = sigExtra; + sigExtra = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig); + exp -= shiftDist; + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig, sigExtra, shiftDist); + sig = sig128.v64; + sigExtra = sig128.v0; + } + return softfloat_roundPackToExtF80(sign, exp, sig, sigExtra, roundingPrecision, status); +} diff --git a/src/cpu/softfloat3e/s_normRoundPackToF128.cc b/src/cpu/softfloat3e/s_normRoundPackToF128.cc new file mode 100644 index 0000000000..14db1ce9b3 --- /dev/null +++ b/src/cpu/softfloat3e/s_normRoundPackToF128.cc @@ -0,0 +1,75 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" + +float128_t softfloat_normRoundPackToF128(bool sign, int32_t exp, uint64_t sig64, uint64_t sig0, struct softfloat_status_t *status) +{ + int8_t shiftDist; + struct uint128 sig128; + uint64_t sigExtra; + struct uint128_extra sig128Extra; + float128_t z; + + if (! sig64) { + exp -= 64; + sig64 = sig0; + sig0 = 0; + } + shiftDist = softfloat_countLeadingZeros64(sig64) - 15; + exp -= shiftDist; + if (0 <= shiftDist) { + if (shiftDist) { + sig128 = softfloat_shortShiftLeft128(sig64, sig0, shiftDist); + sig64 = sig128.v64; + sig0 = sig128.v0; + } + if ((uint32_t) exp < 0x7FFD) { + z.v64 = packToF128UI64(sign, sig64 | sig0 ? exp : 0, sig64); + z.v0 = sig0; + return z; + } + sigExtra = 0; + } else { + sig128Extra = softfloat_shortShiftRightJam128Extra(sig64, sig0, 0, -shiftDist); + sig64 = sig128Extra.v.v64; + sig0 = sig128Extra.v.v0; + sigExtra = sig128Extra.extra; + } + return softfloat_roundPackToF128(sign, exp, sig64, sig0, sigExtra, status); +} diff --git a/src/cpu/softfloat3e/s_normRoundPackToF16.c b/src/cpu/softfloat3e/s_normRoundPackToF16.c new file mode 100644 index 0000000000..36ae237fae --- /dev/null +++ b/src/cpu/softfloat3e/s_normRoundPackToF16.c @@ -0,0 +1,49 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" + +float16 softfloat_normRoundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) +{ + int8_t shiftDist = softfloat_countLeadingZeros16(sig) - 1; + exp -= shiftDist; + if ((4 <= shiftDist) && ((unsigned int) exp < 0x1D)) { + return packToF16UI(sign, sig ? exp : 0, sig<<(shiftDist - 4)); + } else { + return softfloat_roundPackToF16(sign, exp, sig< +#include "internals.h" +#include "primitives.h" + +float32 softfloat_normRoundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) +{ + int8_t shiftDist = softfloat_countLeadingZeros32(sig) - 1; + exp -= shiftDist; + if ((7 <= shiftDist) && ((unsigned int) exp < 0xFD)) { + return packToF32UI(sign, sig ? exp : 0, sig<<(shiftDist - 7)); + } else { + return softfloat_roundPackToF32(sign, exp, sig< +#include "internals.h" +#include "primitives.h" + +float64 softfloat_normRoundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) +{ + int8_t shiftDist = softfloat_countLeadingZeros64(sig) - 1; + exp -= shiftDist; + if ((10 <= shiftDist) && ((unsigned int) exp < 0x7FD)) { + return packToF64UI(sign, sig ? exp : 0, sig<<(shiftDist - 10)); + } else { + return softfloat_roundPackToF64(sign, exp, sig< +#include "internals.h" +#include "primitives.h" + +struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint64_t sig) +{ + int8_t shiftDist; + struct exp32_sig64 z; + + shiftDist = softfloat_countLeadingZeros64(sig); + z.exp = -shiftDist; + z.sig = sig< +#include "internals.h" +#include "primitives.h" + +struct exp32_sig128 softfloat_normSubnormalF128Sig(uint64_t sig64, uint64_t sig0) +{ + int8_t shiftDist; + struct exp32_sig128 z; + + if (! sig64) { + shiftDist = softfloat_countLeadingZeros64(sig0) - 15; + z.exp = -63 - shiftDist; + if (shiftDist < 0) { + z.sig.v64 = sig0>>-shiftDist; + z.sig.v0 = sig0<<(shiftDist & 63); + } else { + z.sig.v64 = sig0< +#include "internals.h" +#include "primitives.h" + +struct exp8_sig16 softfloat_normSubnormalF16Sig(uint16_t sig) +{ + int8_t shiftDist; + struct exp8_sig16 z; + + shiftDist = softfloat_countLeadingZeros16(sig) - 5; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "internals.h" +#include "primitives.h" + +struct exp16_sig32 softfloat_normSubnormalF32Sig(uint32_t sig) +{ + int8_t shiftDist; + struct exp16_sig32 z; + + shiftDist = softfloat_countLeadingZeros32(sig) - 8; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "internals.h" +#include "primitives.h" + +struct exp16_sig64 softfloat_normSubnormalF64Sig(uint64_t sig) +{ + int8_t shiftDist; + struct exp16_sig64 z; + + shiftDist = softfloat_countLeadingZeros64(sig) - 11; + z.exp = 1 - shiftDist; + z.sig = sig< +#include "internals.h" +#include "softfloat.h" + +extFloat80_t packToExtF80_twoargs(uint16_t signExp, uint64_t sig) +{ + extFloat80_t z; + z.signExp = signExp; + z.signif = sig; + return z; +} + +extFloat80_t packToExtF80(bool sign, uint16_t exp, uint64_t sig) +{ + extFloat80_t z; + z.signExp = packToExtF80UI64(sign, exp); + z.signif = sig; + return z; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNExtF80UI.cc b/src/cpu/softfloat3e/s_propagateNaNExtF80UI.cc new file mode 100644 index 0000000000..77d699bb0f --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNExtF80UI.cc @@ -0,0 +1,96 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +extFloat80_t +softfloat_propagateNaNExtF80UI(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, struct softfloat_status_t *status) +{ + bool isSigNaNA, isSigNaNB; + uint64_t uiNonsigA0, uiNonsigB0; + uint16_t uiMagA64, uiMagB64; + extFloat80_t z; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + isSigNaNA = softfloat_isSigNaNExtF80UI(uiA64, uiA0); + isSigNaNB = softfloat_isSigNaNExtF80UI(uiB64, uiB0); + /*------------------------------------------------------------------------ + | Make NaNs non-signaling. + *------------------------------------------------------------------------*/ + uiNonsigA0 = uiA0 | UINT64_C(0xC000000000000000); + uiNonsigB0 = uiB0 | UINT64_C(0xC000000000000000); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (isSigNaNA | isSigNaNB) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) { + if (isSigNaNB) goto returnLargerMag; + if (isNaNExtF80UI(uiB64, uiB0)) goto returnB; + goto returnA; + } else { + if (isNaNExtF80UI(uiA64, uiA0)) goto returnA; + goto returnB; + } + } + returnLargerMag: + uiMagA64 = uiA64 & 0x7FFF; + uiMagB64 = uiB64 & 0x7FFF; + if (uiMagA64 < uiMagB64) goto returnB; + if (uiMagB64 < uiMagA64) goto returnA; + if (uiA0 < uiB0) goto returnB; + if (uiB0 < uiA0) goto returnA; + if (uiA64 < uiB64) goto returnA; + returnB: + z.signExp = uiB64; + z.signif = uiNonsigB0; + return z; + returnA: + z.signExp = uiA64; + z.signif = uiNonsigA0; + return z; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF128UI.cc b/src/cpu/softfloat3e/s_propagateNaNF128UI.cc new file mode 100644 index 0000000000..83a7c24136 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF128UI.cc @@ -0,0 +1,78 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating `uiA64' and +| `uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating `uiB64' and `uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint64_t uiA64, + uint64_t uiA0, + uint64_t uiB64, + uint64_t uiB0, + struct softfloat_status_t *status +) +{ + bool isSigNaNA; + struct uint128 uiZ; + + isSigNaNA = softfloat_isSigNaNF128UI(uiA64, uiA0); + if (isSigNaNA || softfloat_isSigNaNF128UI(uiB64, uiB0)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) goto returnNonsigA; + } + if (isNaNF128UI(uiA64, uiA0)) { + returnNonsigA: + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + } else { + uiZ.v64 = uiB64; + uiZ.v0 = uiB0; + } + uiZ.v64 |= UINT64_C(0x0000800000000000); + return uiZ; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF16UI.c b/src/cpu/softfloat3e/s_propagateNaNF16UI.c new file mode 100644 index 0000000000..0a92c57f02 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF16UI.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 16-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint16_t softfloat_propagateNaNF16UI(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF16UI(uiA); + if (isSigNaNA || softfloat_isSigNaNF16UI(uiB)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) return uiA | 0x0200; + } + return (isNaNF16UI(uiA) ? uiA : uiB) | 0x0200; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF32UI.c b/src/cpu/softfloat3e/s_propagateNaNF32UI.c new file mode 100644 index 0000000000..d5db3d24e8 --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF32UI.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_propagateNaNF32UI(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF32UI(uiA); + if (isSigNaNA || softfloat_isSigNaNF32UI(uiB)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) return uiA | 0x00400000; + } + return (isNaNF32UI(uiA) ? uiA : uiB) | 0x00400000; +} diff --git a/src/cpu/softfloat3e/s_propagateNaNF64UI.c b/src/cpu/softfloat3e/s_propagateNaNF64UI.c new file mode 100644 index 0000000000..3bb2ead86a --- /dev/null +++ b/src/cpu/softfloat3e/s_propagateNaNF64UI.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| Interpreting `uiA' and `uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either `uiA' or `uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_propagateNaNF64UI(uint64_t uiA, uint64_t uiB, struct softfloat_status_t *status) +{ + bool isSigNaNA; + + isSigNaNA = softfloat_isSigNaNF64UI(uiA); + if (isSigNaNA || softfloat_isSigNaNF64UI(uiB)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); + if (isSigNaNA) return uiA | UINT64_C(0x0008000000000000); + } + return (isNaNF64UI(uiA) ? uiA : uiB) | UINT64_C(0x0008000000000000); +} diff --git a/src/cpu/softfloat3e/s_roundPackToExtF80.cc b/src/cpu/softfloat3e/s_roundPackToExtF80.cc new file mode 100644 index 0000000000..ec63283e12 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToExtF80.cc @@ -0,0 +1,224 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t + softfloat_roundPackToExtF80(bool sign, int32_t exp, uint64_t sig, uint64_t sigExtra, uint8_t roundingPrecision, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint64_t roundIncrement, roundMask, roundBits; + bool isTiny, doIncrement; + struct uint64_extra sig64Extra; + uint64_t sigExact; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + if (roundingPrecision == 80) goto precision80; + if (roundingPrecision == 64) { + roundIncrement = UINT64_C(0x0000000000000400); + roundMask = UINT64_C(0x00000000000007FF); + } else if (roundingPrecision == 32) { + roundIncrement = UINT64_C(0x0000008000000000); + roundMask = UINT64_C(0x000000FFFFFFFFFF); + } else { + goto precision80; + } + sig |= (sigExtra != 0); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? roundMask : 0; + } + roundBits = sig & roundMask; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FFD <= (uint32_t) (exp - 1)) { + if (exp <= 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < 0) || (sig <= (uint64_t) (sig + roundIncrement)); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; + } + else { + sig = softfloat_shiftRightJam64(sig, 1 - exp); + roundBits = sig & roundMask; + sigExact = sig; + sig += roundIncrement; + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + roundIncrement = roundMask + 1; + if (roundNearEven && (roundBits<<1 == roundIncrement)) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + return packToExtF80(sign, exp, sig); + } + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { + if (! softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_overflow); + exp -= 0x6000; + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && ((uint64_t) (sig + roundIncrement) < sig))) { + goto overflow; + } + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigExact = sig; + sig = (uint64_t) (sig + roundIncrement); + if (sig < roundIncrement) { + ++exp; + sig = UINT64_C(0x8000000000000000); + sigExact >>= 1; // must scale also, or else later tests will fail + } + roundIncrement = roundMask + 1; + if (roundNearEven && (roundBits<<1 == roundIncrement)) { + roundMask |= roundIncrement; + } + sig &= ~roundMask; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > sigExact) softfloat_setRoundingUp(status); + } + return packToExtF80(sign, exp, sig); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + precision80: + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + doIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FFD <= (uint32_t) (exp - 1)) { + if (exp <= 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < 0) || ! doIncrement || (sig < UINT64_C(0xFFFFFFFFFFFFFFFF)); + if (isTiny && sig && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 0x6000; + } + else { + sig64Extra = softfloat_shiftRightJam64Extra(sig, sigExtra, 1 - exp); + exp = 0; + sig = sig64Extra.v; + sigExtra = sig64Extra.extra; + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (isTiny) + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + doIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) && sigExtra; + } + if (doIncrement) { + sigExact = sig; + ++sig; + sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + exp = ((sig & UINT64_C(0x8000000000000000)) != 0); + if (sig > sigExact) + softfloat_setRoundingUp(status); + } + return packToExtF80(sign, exp, sig); + } + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { + if (! softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_overflow); + exp -= 0x6000; + } + if ((0x7FFE < exp) || ((exp == 0x7FFE) && (sig == UINT64_C(0xFFFFFFFFFFFFFFFF)) && doIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + roundMask = 0; + overflow: + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + if (roundNearEven + || (roundingMode == softfloat_round_near_maxMag) + || (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) + ) { + exp = 0x7FFF; + sig = UINT64_C(0x8000000000000000); + softfloat_setRoundingUp(status); + } else { + exp = 0x7FFE; + sig = ~roundMask; + } + return packToExtF80(sign, exp, sig); + } + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + if (doIncrement) { + sigExact = sig; + ++sig; + if (! sig) { + ++exp; + sig = UINT64_C(0x8000000000000000); + sigExact >>= 1; // must scale also, or else later tests will fail + } else { + sig &= ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF)) & roundNearEven); + } + if (sig > sigExact) + softfloat_setRoundingUp(status); + } + else { + if (! sig) exp = 0; + } + return packToExtF80(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundPackToF128.cc b/src/cpu/softfloat3e/s_roundPackToF128.cc new file mode 100644 index 0000000000..46741e5e92 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF128.cc @@ -0,0 +1,102 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +// trimmed for Bochs to support only 'softfloat_round_nearest_even' rounding mode +float128_t + softfloat_roundPackToF128(bool sign, int32_t exp, uint64_t sig64, uint64_t sig0, uint64_t sigExtra, struct softfloat_status_t *status) +{ + bool doIncrement, isTiny; + struct uint128_extra sig128Extra; + struct uint128 sig128; + float128_t z; + + sigExtra = 0; // artificially reduce precision to match hardware x86 which uses only 67-bit + sig0 &= UINT64_C(0xFFFFFFFF00000000); // do 80 bits for now + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FFD <= (uint32_t) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || ! doIncrement || + softfloat_lt128(sig64, sig0, UINT64_C(0x0001FFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)); + sig128Extra = softfloat_shiftRightJam128Extra(sig64, sig0, sigExtra, -exp); + sig64 = sig128Extra.v.v64; + sig0 = sig128Extra.v.v0; + sigExtra = sig128Extra.extra; + exp = 0; + if (isTiny && sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + doIncrement = (UINT64_C(0x8000000000000000) <= sigExtra); + } else if ((0x7FFD < exp) || ((exp == 0x7FFD) + && softfloat_eq128(sig64, sig0, UINT64_C(0x0001FFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)) + && doIncrement) + ) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow | softfloat_flag_inexact); + z.v64 = packToF128UI64(sign, 0x7FFF, 0); + z.v0 = 0; + return z; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (sigExtra) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + } + if (doIncrement) { + sig128 = softfloat_add128(sig64, sig0, 0, 1); + sig64 = sig128.v64; + sig0 = sig128.v0 & ~(uint64_t) (! (sigExtra & UINT64_C(0x7FFFFFFFFFFFFFFF))); + } else { + if (! (sig64 | sig0)) exp = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + z.v64 = packToF128UI64(sign, exp, sig64); + z.v0 = sig0; + return z; +} diff --git a/src/cpu/softfloat3e/s_roundPackToF16.c b/src/cpu/softfloat3e/s_roundPackToF16.c new file mode 100644 index 0000000000..c262d00b14 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF16.c @@ -0,0 +1,104 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 softfloat_roundPackToF16(bool sign, int16_t exp, uint16_t sig, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint8_t roundIncrement, roundBits; + bool isTiny; + uint16_t uiZ; + uint16_t sigRef; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x8; + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0xF : 0; + } + roundBits = sig & 0xF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x1D <= (unsigned int) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || (sig + roundIncrement < 0x8000); + sig = softfloat_shiftRightJam32(sig, -exp); + exp = 0; + roundBits = sig & 0xF; + if (isTiny) { + if (! softfloat_isMaskedException(status, softfloat_flag_underflow) || roundBits) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF16UI(sign, 0, 0); + } + } + } else if ((0x1D < exp) || (0x8000 <= sig + roundIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow); + if (roundBits || softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (roundIncrement != 0) softfloat_setRoundingUp(status); + } + uiZ = packToF16UI(sign, 0x1F, 0) - ! roundIncrement; + return uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigRef = sig; + sig = (sig + roundIncrement)>>4; + sig &= ~(uint16_t) (! (roundBits ^ 8) & roundNearEven); + if (! sig) exp = 0; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if ((sig << 4) > sigRef) softfloat_setRoundingUp(status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF16UI(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundPackToF32.c b/src/cpu/softfloat3e/s_roundPackToF32.c new file mode 100644 index 0000000000..03a4e36a00 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF32.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float32 softfloat_roundPackToF32(bool sign, int16_t exp, uint32_t sig, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint8_t roundIncrement, roundBits; + bool isTiny; + uint32_t uiZ; + uint32_t sigRef; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x40; + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x7F : 0; + } + roundBits = sig & 0x7F; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0xFD <= (unsigned int) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || (sig + roundIncrement < 0x80000000); + if (isTiny && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 192; + } + else { + sig = softfloat_shiftRightJam32(sig, -exp); + exp = 0; + roundBits = sig & 0x7F; + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(sign, 0, 0); + } + if (roundBits) softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } else if ((0xFD < exp) || (0x80000000 <= sig + roundIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow); + if (roundBits || softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (roundIncrement != 0) softfloat_setRoundingUp(status); + } + uiZ = packToF32UI(sign, 0xFF, 0) - ! roundIncrement; + return uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigRef = sig; + sig = (sig + roundIncrement)>>7; + sig &= ~(uint32_t) (! (roundBits ^ 0x40) & roundNearEven); + if (! sig) exp = 0; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if ((sig << 7) > sigRef) softfloat_setRoundingUp(status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF32UI(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundPackToF64.c b/src/cpu/softfloat3e/s_roundPackToF64.c new file mode 100644 index 0000000000..713fd69404 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundPackToF64.c @@ -0,0 +1,108 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 softfloat_roundPackToF64(bool sign, int16_t exp, uint64_t sig, struct softfloat_status_t *status) +{ + uint8_t roundingMode; + bool roundNearEven; + uint16_t roundIncrement, roundBits; + bool isTiny; + uint64_t uiZ; + uint64_t sigRef; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundingMode = softfloat_getRoundingMode(status); + roundNearEven = (roundingMode == softfloat_round_near_even); + roundIncrement = 0x200; + if (! roundNearEven && (roundingMode != softfloat_round_near_maxMag)) { + roundIncrement = + (roundingMode == (sign ? softfloat_round_min : softfloat_round_max)) ? 0x3FF : 0; + } + roundBits = sig & 0x3FF; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (0x7FD <= (uint16_t) exp) { + if (exp < 0) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + isTiny = (exp < -1) || (sig + roundIncrement < UINT64_C(0x8000000000000000)); + if (isTiny && ! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + exp += 1536; + } + else { + sig = softfloat_shiftRightJam64(sig, -exp); + exp = 0; + roundBits = sig & 0x3FF; + if (isTiny) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(sign, 0, 0); + } + if (roundBits) softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + } else if ((0x7FD < exp) || (UINT64_C(0x8000000000000000) <= sig + roundIncrement)) { + /*---------------------------------------------------------------- + *----------------------------------------------------------------*/ + softfloat_raiseFlags(status, softfloat_flag_overflow); + if (roundBits || softfloat_isMaskedException(status, softfloat_flag_overflow)) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if (roundIncrement != 0) softfloat_setRoundingUp(status); + } + uiZ = packToF64UI(sign, 0x7FF, 0) - ! roundIncrement; + return uiZ; + } + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + sigRef = sig; + sig = (sig + roundIncrement)>>10; + sig &= ~(uint64_t) (! (roundBits ^ 0x200) & roundNearEven); + if (! sig) exp = 0; + if (roundBits) { + softfloat_raiseFlags(status, softfloat_flag_inexact); + if ((sig << 10) > sigRef) softfloat_setRoundingUp(status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + return packToF64UI(sign, exp, sig); +} diff --git a/src/cpu/softfloat3e/s_roundToI32.c b/src/cpu/softfloat3e/s_roundToI32.c new file mode 100644 index 0000000000..a7a0b13d79 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToI32.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int32_t softfloat_roundToI32(bool sign, uint64_t sig, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t roundIncrement, roundBits; + uint32_t sig32; + union { uint32_t ui; int32_t i; } uZ; + int32_t z; + uint64_t absSigExact = sig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundIncrement = 0x800; + if ((roundingMode != softfloat_round_near_maxMag) && (roundingMode != softfloat_round_near_even)) { + roundIncrement = 0; + if (sign ? (roundingMode == softfloat_round_min) : (roundingMode == softfloat_round_max)) { + roundIncrement = 0xFFF; + } + } + roundBits = sig & 0xFFF; + sig += roundIncrement; + if (sig & UINT64_C(0xFFFFF00000000000)) goto invalid; + sig32 = sig>>12; + if ((roundBits == 0x800) && (roundingMode == softfloat_round_near_even)) { + sig32 &= ~(uint32_t) 1; + } + uZ.ui = sign ? -sig32 : sig32; + z = uZ.i; + if (z && ((z < 0) ^ sign)) goto invalid; + if (roundBits) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (((uint64_t)sig32 << 12) > absSigExact) + softfloat_setRoundingUp(status); + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? i32_fromNegOverflow : i32_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_roundToI64.c b/src/cpu/softfloat3e/s_roundToI64.c new file mode 100644 index 0000000000..72d421889e --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToI64.c @@ -0,0 +1,77 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +int64_t + softfloat_roundToI64(bool sign, uint64_t sig, uint64_t sigExtra, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + union { uint64_t ui; int64_t i; } uZ; + int64_t z; + uint64_t absSigExact = sig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((roundingMode == softfloat_round_near_maxMag) || (roundingMode == softfloat_round_near_even)) { + if (UINT64_C(0x8000000000000000) <= sigExtra) goto increment; + } else { + if (sigExtra + && (sign ? (roundingMode == softfloat_round_min) : (roundingMode == softfloat_round_max))) { + increment: + ++sig; + if (!sig) goto invalid; + if ((sigExtra == UINT64_C(0x8000000000000000)) && (roundingMode == softfloat_round_near_even)) { + sig &= ~(uint64_t) 1; + } + } + } + uZ.ui = sign ? -sig : sig; + z = uZ.i; + if (z && ((z < 0) ^ sign)) goto invalid; + if (sigExtra) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > absSigExact) + softfloat_setRoundingUp(status); + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? i64_fromNegOverflow : i64_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_roundToUI32.c b/src/cpu/softfloat3e/s_roundToUI32.c new file mode 100644 index 0000000000..d2956b0ac7 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToUI32.c @@ -0,0 +1,79 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint32_t + softfloat_roundToUI32(bool sign, uint64_t sig, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint16_t roundIncrement, roundBits; + uint32_t z; + uint64_t absSigExact = sig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + roundIncrement = 0x800; + if ((roundingMode != softfloat_round_near_maxMag) && (roundingMode != softfloat_round_near_even)) { + roundIncrement = 0; + if (sign) { + if (!sig) return 0; + if (roundingMode == softfloat_round_min) goto invalid; + } else { + if (roundingMode == softfloat_round_max) roundIncrement = 0xFFF; + } + } + roundBits = sig & 0xFFF; + sig += roundIncrement; + if (sig & UINT64_C(0xFFFFF00000000000)) goto invalid; + z = sig>>12; + if ((roundBits == 0x800) && (roundingMode == softfloat_round_near_even)) { + z &= ~(uint32_t) 1; + } + if (sign && z) goto invalid; + if (roundBits) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (((uint64_t)z << 12) > absSigExact) + softfloat_setRoundingUp(status); + } + return z; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? ui32_fromNegOverflow : ui32_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_roundToUI64.c b/src/cpu/softfloat3e/s_roundToUI64.c new file mode 100644 index 0000000000..75120a7fe8 --- /dev/null +++ b/src/cpu/softfloat3e/s_roundToUI64.c @@ -0,0 +1,76 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +uint64_t + softfloat_roundToUI64(bool sign, uint64_t sig, uint64_t sigExtra, uint8_t roundingMode, bool exact, struct softfloat_status_t *status) +{ + uint64_t absSigExact = sig; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if ((roundingMode == softfloat_round_near_maxMag) || (roundingMode == softfloat_round_near_even)) { + if (UINT64_C(0x8000000000000000) <= sigExtra) goto increment; + } else { + if (sign) { + if (!(sig | sigExtra)) return 0; + if (roundingMode == softfloat_round_min) goto invalid; + } else { + if ((roundingMode == softfloat_round_max) && sigExtra) { + increment: + ++sig; + if (!sig) goto invalid; + if ((sigExtra == UINT64_C(0x8000000000000000)) && (roundingMode == softfloat_round_near_even)) { + sig &= ~(uint64_t) 1; + } + } + } + } + if (sign && sig) goto invalid; + if (sigExtra) { + if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact); + if (sig > absSigExact) + softfloat_setRoundingUp(status); + } + return sig; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + invalid: + softfloat_raiseFlags(status, softfloat_flag_invalid); + return sign ? ui64_fromNegOverflow : ui64_fromPosOverflow; +} diff --git a/src/cpu/softfloat3e/s_shiftRightJam128.cc b/src/cpu/softfloat3e/s_shiftRightJam128.cc new file mode 100644 index 0000000000..11fb26abfc --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam128.cc @@ -0,0 +1,65 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shiftRightJam128 + +struct uint128 + softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128 z; + + if (dist < 64) { + u8NegDist = -dist; + z.v64 = a64>>dist; + z.v0 = + a64<<(u8NegDist & 63) | a0>>dist + | ((uint64_t) (a0<<(u8NegDist & 63)) != 0); + } else { + z.v64 = 0; + z.v0 = + (dist < 127) + ? a64>>(dist & 63) + | (((a64 & (((uint64_t) 1<<(dist & 63)) - 1)) | a0) + != 0) + : ((a64 | a0) != 0); + } + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam128Extra.cc b/src/cpu/softfloat3e/s_shiftRightJam128Extra.cc new file mode 100644 index 0000000000..7f4b3fa825 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam128Extra.cc @@ -0,0 +1,73 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shiftRightJam128Extra + +struct uint128_extra + softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint32_t dist) +{ + uint8_t u8NegDist; + struct uint128_extra z; + + u8NegDist = -dist; + if (dist < 64) { + z.v.v64 = a64>>dist; + z.v.v0 = a64<<(u8NegDist & 63) | a0>>dist; + z.extra = a0<<(u8NegDist & 63); + } else { + z.v.v64 = 0; + if (dist == 64) { + z.v.v0 = a64; + z.extra = a0; + } else { + extra |= a0; + if (dist < 128) { + z.v.v0 = a64>>(dist & 63); + z.extra = a64<<(u8NegDist & 63); + } else { + z.v.v0 = 0; + z.extra = (dist == 128) ? a64 : (a64 != 0); + } + } + } + z.extra |= (extra != 0); + return z; + +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam256M.c b/src/cpu/softfloat3e/s_shiftRightJam256M.c new file mode 100644 index 0000000000..654e012340 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam256M.c @@ -0,0 +1,113 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitiveTypes.h" + +#ifndef softfloat_shiftRightJam256M + +static void softfloat_shortShiftRightJamM(uint8_t size_words, const uint64_t *aPtr, uint8_t dist, uint64_t *zPtr) +{ + uint8_t uNegDist; + unsigned int index, lastIndex; + uint64_t partWordZ, wordA; + + uNegDist = -dist; + index = indexWordLo(size_words); + lastIndex = indexWordHi(size_words); + wordA = aPtr[index]; + partWordZ = wordA>>dist; + if (partWordZ<>dist; + } + zPtr[index] = partWordZ; + +} + +void softfloat_shiftRightJam256M(const uint64_t *aPtr, uint32_t dist, uint64_t *zPtr) +{ + uint64_t wordJam; + uint32_t wordDist; + uint64_t *ptr; + uint8_t i, innerDist; + + wordJam = 0; + wordDist = dist>>6; + if (wordDist) { + if (4 < wordDist) wordDist = 4; + ptr = (uint64_t *) (aPtr + indexMultiwordLo(4, wordDist)); + i = wordDist; + do { + wordJam = *ptr++; + if (wordJam) break; + --i; + } while (i); + ptr = zPtr; + } + if (wordDist < 4) { + aPtr += indexMultiwordHiBut(4, wordDist); + innerDist = dist & 63; + if (innerDist) { + softfloat_shortShiftRightJamM( + 4 - wordDist, + aPtr, + innerDist, + zPtr + indexMultiwordLoBut(4, wordDist) + ); + if (! wordDist) goto wordJam; + } else { + aPtr += indexWordLo(4 - wordDist); + ptr = zPtr + indexWordLo(4); + for (i = 4 - wordDist; i; --i) { + *ptr = *aPtr; + aPtr += wordIncr; + ptr += wordIncr; + } + } + ptr = zPtr + indexMultiwordHi(4, wordDist); + } + do { + *ptr++ = 0; + --wordDist; + } while (wordDist); + wordJam: + if (wordJam) zPtr[indexWordLo(4)] |= 1; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam32.c b/src/cpu/softfloat3e/s_shiftRightJam32.c new file mode 100644 index 0000000000..638aa02948 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam32.c @@ -0,0 +1,45 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_shiftRightJam32 + +uint32_t softfloat_shiftRightJam32(uint32_t a, uint16_t dist) +{ + return (dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0); +} + +#endif diff --git a/src/cpu/softfloat3e/s_shiftRightJam64.c b/src/cpu/softfloat3e/s_shiftRightJam64.c new file mode 100644 index 0000000000..03cf5e6926 --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam64.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_shiftRightJam64 + +uint64_t softfloat_shiftRightJam64(uint64_t a, uint32_t dist) +{ + return (dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0); +} + +#endif + diff --git a/src/cpu/softfloat3e/s_shiftRightJam64Extra.c b/src/cpu/softfloat3e/s_shiftRightJam64Extra.c new file mode 100644 index 0000000000..a80bafb35a --- /dev/null +++ b/src/cpu/softfloat3e/s_shiftRightJam64Extra.c @@ -0,0 +1,57 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shiftRightJam64Extra + +struct uint64_extra + softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint32_t dist) +{ + struct uint64_extra z; + + if (dist < 64) { + z.v = a>>dist; + z.extra = a<<(-dist & 63); + } else { + z.v = 0; + z.extra = (dist == 64) ? a : (a != 0); + } + z.extra |= (extra != 0); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shortShiftLeft128.cc b/src/cpu/softfloat3e/s_shortShiftLeft128.cc new file mode 100644 index 0000000000..dc24172cd7 --- /dev/null +++ b/src/cpu/softfloat3e/s_shortShiftLeft128.cc @@ -0,0 +1,51 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_shortShiftLeft128 + +struct uint128 + softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + struct uint128 z; + + z.v64 = a64<>(-dist & 63); + z.v0 = a0< +#include "softfloat_types.h" + +#ifndef softfloat_shortShiftRight128 + +struct uint128 + softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint8_t dist) +{ + struct uint128 z; + + z.v64 = a64>>dist; + z.v0 = a64<<(-dist & 63) | a0>>dist; + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_shortShiftRightJam64.c b/src/cpu/softfloat3e/s_shortShiftRightJam64.c new file mode 100644 index 0000000000..cfee2a6790 --- /dev/null +++ b/src/cpu/softfloat3e/s_shortShiftRightJam64.c @@ -0,0 +1,46 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include + +#ifndef softfloat_shortShiftRightJam64 + +uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint8_t dist) +{ + return a>>dist | ((a & (((uint64_t) 1< +#include "softfloat_types.h" + +#ifndef softfloat_shortShiftRightJam64Extra + +struct uint64_extra + softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint8_t dist) +{ + struct uint64_extra z; + + z.v = a>>dist; + z.extra = a<<(-dist & 63) | (extra != 0); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_sub128.cc b/src/cpu/softfloat3e/s_sub128.cc new file mode 100644 index 0000000000..d5d5f941b8 --- /dev/null +++ b/src/cpu/softfloat3e/s_sub128.cc @@ -0,0 +1,50 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "softfloat_types.h" + +#ifndef softfloat_sub128 + +struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) +{ + struct uint128 z; + + z.v0 = a0 - b0; + z.v64 = a64 - b64 - (a0 < b0); + return z; +} + +#endif diff --git a/src/cpu/softfloat3e/s_sub256M.c b/src/cpu/softfloat3e/s_sub256M.c new file mode 100644 index 0000000000..8b2f6e2fd4 --- /dev/null +++ b/src/cpu/softfloat3e/s_sub256M.c @@ -0,0 +1,59 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "primitiveTypes.h" + +#ifndef softfloat_sub256M + +void softfloat_sub256M(const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr) +{ + unsigned int index; + uint8_t borrow; + uint64_t wordA, wordB; + + index = indexWordLo(4); + borrow = 0; + for (;;) { + wordA = aPtr[index]; + wordB = bPtr[index]; + zPtr[index] = wordA - wordB - borrow; + if (index == indexWordHi(4)) break; + borrow = borrow ? (wordA <= wordB) : (wordA < wordB); + index += wordIncr; + } +} + +#endif diff --git a/src/cpu/softfloat3e/s_subMagsExtF80.cc b/src/cpu/softfloat3e/s_subMagsExtF80.cc new file mode 100644 index 0000000000..3a75cd768a --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsExtF80.cc @@ -0,0 +1,154 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +extFloat80_t + softfloat_subMagsExtF80(uint16_t uiA64, uint64_t uiA0, uint16_t uiB64, uint64_t uiB0, bool signZ, struct softfloat_status_t *status) +{ + int32_t expA; + uint64_t sigA; + int32_t expB; + uint64_t sigB; + int32_t expDiff; + int32_t expZ; + uint64_t sigExtra; + struct uint128 sig128; + struct exp32_sig64 normExpSig; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expExtF80UI64(uiA64); + sigA = uiA0; + expB = expExtF80UI64(uiB64); + sigB = uiB0; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (expA == 0x7FFF) { + if ((sigA<<1)) goto propagateNaN; + if (expB == 0x7FFF) { + if ((sigB<<1)) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0); + } + if (sigB && ! expB) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80_twoargs(uiA64, uiA0); + } + if (expB == 0x7FFF) { + if ((sigB<<1)) goto propagateNaN; + if (sigA && ! expA) + softfloat_raiseFlags(status, softfloat_flag_denormal); + return packToExtF80(signZ ^ 1, 0x7FFF, UINT64_C(0x8000000000000000)); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expA) { + if (! sigA) { + if (! expB) { + if (sigB) { + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + return softfloat_roundPackToExtF80(signZ ^ 1, expB, sigB, 0, softfloat_extF80_roundingPrecision(status), status); + } + return packToExtF80((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + return softfloat_roundPackToExtF80(signZ ^ 1, expB, sigB, 0, softfloat_extF80_roundingPrecision(status), status); + } + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigA); + expA = normExpSig.exp + 1; + sigA = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (! expB) { + if (! sigB) + return softfloat_roundPackToExtF80(signZ, expA, sigA, 0, softfloat_extF80_roundingPrecision(status), status); + + softfloat_raiseFlags(status, softfloat_flag_denormal); + normExpSig = softfloat_normSubnormalExtF80Sig(sigB); + expB = normExpSig.exp + 1; + sigB = normExpSig.sig; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (0 < expDiff) goto expABigger; + if (expDiff < 0) goto expBBigger; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expZ = expA; + sigExtra = 0; + if (sigB < sigA) goto aBigger; + if (sigA < sigB) goto bBigger; + return packToExtF80((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expBBigger: + sig128 = softfloat_shiftRightJam128(sigA, 0, -expDiff); + sigA = sig128.v64; + sigExtra = sig128.v0; + expZ = expB; + bBigger: + signZ = ! signZ; + sig128 = softfloat_sub128(sigB, 0, sigA, sigExtra); + goto normRoundPack; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expABigger: + sig128 = softfloat_shiftRightJam128(sigB, 0, expDiff); + sigB = sig128.v64; + sigExtra = sig128.v0; + expZ = expA; + aBigger: + sig128 = softfloat_sub128(sigA, 0, sigB, sigExtra); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + normRoundPack: + return + softfloat_normRoundPackToExtF80( + signZ, expZ, sig128.v64, sig128.v0, softfloat_extF80_roundingPrecision(status), status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status); +} diff --git a/src/cpu/softfloat3e/s_subMagsF128.cc b/src/cpu/softfloat3e/s_subMagsF128.cc new file mode 100644 index 0000000000..f39e6c02d8 --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsF128.cc @@ -0,0 +1,131 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float128_t + softfloat_subMagsF128( + uint64_t uiA64, + uint64_t uiA0, + uint64_t uiB64, + uint64_t uiB0, + bool signZ, + struct softfloat_status_t *status +) +{ + int32_t expA; + struct uint128 sigA; + int32_t expB; + struct uint128 sigB, sigZ; + int32_t expDiff, expZ; + struct uint128 uiZ; + + expA = expF128UI64(uiA64); + sigA.v64 = fracF128UI64(uiA64); + sigA.v0 = uiA0; + expB = expF128UI64(uiB64); + sigB.v64 = fracF128UI64(uiB64); + sigB.v0 = uiB0; + sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 4); + sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 4); + expDiff = expA - expB; + if (0 < expDiff) goto expABigger; + if (expDiff < 0) goto expBBigger; + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + uiZ.v64 = defaultNaNF128UI64; + uiZ.v0 = defaultNaNF128UI0; + return uiZ; + } + expZ = expA; + if (! expZ) expZ = 1; + if (sigB.v64 < sigA.v64) goto aBigger; + if (sigA.v64 < sigB.v64) goto bBigger; + if (sigB.v0 < sigA.v0) goto aBigger; + if (sigA.v0 < sigB.v0) goto bBigger; + uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + uiZ.v0 = 0; + return uiZ; + expBBigger: + if (expB == 0x7FFF) { + if (sigB.v64 | sigB.v0) goto propagateNaN; + uiZ.v64 = packToF128UI64(signZ ^ 1, 0x7FFF, 0); + uiZ.v0 = 0; + return uiZ; + } + if (expA) { + sigA.v64 |= UINT64_C(0x0010000000000000); + } else { + ++expDiff; + if (! expDiff) goto newlyAlignedBBigger; + } + sigA = softfloat_shiftRightJam128(sigA.v64, sigA.v0, -expDiff); + newlyAlignedBBigger: + expZ = expB; + sigB.v64 |= UINT64_C(0x0010000000000000); + bBigger: + signZ = ! signZ; + sigZ = softfloat_sub128(sigB.v64, sigB.v0, sigA.v64, sigA.v0); + goto normRoundPack; + expABigger: + if (expA == 0x7FFF) { + if (sigA.v64 | sigA.v0) goto propagateNaN; + uiZ.v64 = uiA64; + uiZ.v0 = uiA0; + return uiZ; + } + if (expB) { + sigB.v64 |= UINT64_C(0x0010000000000000); + } else { + --expDiff; + if (! expDiff) goto newlyAlignedABigger; + } + sigB = softfloat_shiftRightJam128(sigB.v64, sigB.v0, expDiff); + newlyAlignedABigger: + expZ = expA; + sigA.v64 |= UINT64_C(0x0010000000000000); + aBigger: + sigZ = softfloat_sub128(sigA.v64, sigA.v0, sigB.v64, sigB.v0); + normRoundPack: + return softfloat_normRoundPackToF128(signZ, expZ - 5, sigZ.v64, sigZ.v0, status); + propagateNaN: + uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status); + return uiZ; +} diff --git a/src/cpu/softfloat3e/s_subMagsF16.c b/src/cpu/softfloat3e/s_subMagsF16.c new file mode 100644 index 0000000000..6241d0ee53 --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsF16.c @@ -0,0 +1,190 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float16 softfloat_subMagsF16(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status) +{ + int8_t expA; + uint16_t sigA; + int8_t expB; + uint16_t sigB; + int8_t expDiff; + uint16_t uiZ; + int16_t sigDiff; + bool signZ; + int8_t shiftDist, expZ; + uint16_t sigZ, sigX, sigY; + uint32_t sig32Z; + int8_t roundingMode; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF16UI(uiA); + sigA = fracF16UI(uiA); + expB = expF16UI(uiB); + sigB = fracF16UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expA == 0x1F) { + if (sigA | sigB) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF16UI; + } + if (!expA && (sigA | sigB)) softfloat_raiseFlags(status, softfloat_flag_denormal); + sigDiff = sigA - sigB; + if (! sigDiff) { + return packToF16UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + if (expA) --expA; + signZ = signF16UI(uiA); + if (sigDiff < 0) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros16(sigDiff) - 5; + expZ = expA - shiftDist; + if (expZ < 0) { + shiftDist = expA; + expZ = 0; + } + sigZ = sigDiff<>16; + if (sig32Z & 0xFFFF) { + sigZ |= 1; + } else { + if (! (sigZ & 0xF) && ((unsigned int) expZ < 0x1E)) { + sigZ >>= 4; + goto pack; + } + } + return softfloat_roundPackToF16(signZ, expZ, sigZ, status); + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + propagateNaN: + return softfloat_propagateNaNF16UI(uiA, uiB, status); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + subEpsilon: + roundingMode = softfloat_getRoundingMode(status); + if (roundingMode != softfloat_round_near_even) { + if ((roundingMode == softfloat_round_minMag) + || (roundingMode == (signF16UI(uiZ) ? softfloat_round_max : softfloat_round_min))) { + --uiZ; + } + } + softfloat_raiseFlags(status, softfloat_flag_inexact); + return uiZ; + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + pack: + return packToF16UI(signZ, expZ, sigZ); +} diff --git a/src/cpu/softfloat3e/s_subMagsF32.c b/src/cpu/softfloat3e/s_subMagsF32.c new file mode 100644 index 0000000000..115e2906c2 --- /dev/null +++ b/src/cpu/softfloat3e/s_subMagsF32.c @@ -0,0 +1,151 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float32 softfloat_subMagsF32(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status) +{ + int16_t expA; + uint32_t sigA; + int16_t expB; + uint32_t sigB; + int16_t expDiff; + int32_t sigDiff; + bool signZ; + int8_t shiftDist; + int16_t expZ; + uint32_t sigX, sigY; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF32UI(uiA); + sigA = fracF32UI(uiA); + expB = expF32UI(uiB); + sigB = fracF32UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expA == 0xFF) { + if (sigA | sigB) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF32UI; + } + if (!expA && (sigA | sigB)) softfloat_raiseFlags(status, softfloat_flag_denormal); + sigDiff = sigA - sigB; + if (! sigDiff) { + return packToF32UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + if (expA) --expA; + signZ = signF32UI(uiA); + if (sigDiff < 0) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros32(sigDiff) - 8; + expZ = expA - shiftDist; + if (expZ < 0) { + shiftDist = expA; + expZ = 0; + } + if (!expZ && sigDiff) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF32UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + return packToF32UI(signZ, expZ, sigDiff< +#include "internals.h" +#include "primitives.h" +#include "specialize.h" +#include "softfloat.h" + +float64 softfloat_subMagsF64(uint64_t uiA, uint64_t uiB, bool signZ, struct softfloat_status_t *status) +{ + int16_t expA; + uint64_t sigA; + int16_t expB; + uint64_t sigB; + int16_t expDiff; + int64_t sigDiff; + int8_t shiftDist; + int16_t expZ; + uint64_t sigZ; + + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expA = expF64UI(uiA); + sigA = fracF64UI(uiA); + expB = expF64UI(uiB); + sigB = fracF64UI(uiB); + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + if (softfloat_denormalsAreZeros(status)) { + if (!expA) sigA = 0; + if (!expB) sigB = 0; + } + /*------------------------------------------------------------------------ + *------------------------------------------------------------------------*/ + expDiff = expA - expB; + if (! expDiff) { + /*-------------------------------------------------------------------- + *--------------------------------------------------------------------*/ + if (expA == 0x7FF) { + if (sigA | sigB) goto propagateNaN; + softfloat_raiseFlags(status, softfloat_flag_invalid); + return defaultNaNF64UI; + } + if (!expA && (sigA | sigB)) softfloat_raiseFlags(status, softfloat_flag_denormal); + sigDiff = sigA - sigB; + if (! sigDiff) { + return packToF64UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0); + } + if (expA) --expA; + if (sigDiff < 0) { + signZ = ! signZ; + sigDiff = -sigDiff; + } + shiftDist = softfloat_countLeadingZeros64(sigDiff) - 11; + expZ = expA - shiftDist; + if (expZ < 0) { + shiftDist = expA; + expZ = 0; + } + if (!expZ && sigDiff) { + if (softfloat_flushUnderflowToZero(status)) { + softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact); + return packToF64UI(signZ, 0, 0); + } + if (! softfloat_isMaskedException(status, softfloat_flag_underflow)) { + softfloat_raiseFlags(status, softfloat_flag_underflow); + } + } + return packToF64UI(signZ, expZ, sigDiff< + +#include "primitives.h" +#include "primitiveTypes.h" + +/*---------------------------------------------------------------------------- +| 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'. +*----------------------------------------------------------------------------*/ + +static __inline void mul128By64To192(uint64_t a64, uint64_t a0, uint64_t b, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) +{ + uint64_t zPtr[4]; + + softfloat_mul128To256M(a64, a0, 0, b, (uint64_t*) zPtr); + + assert(zPtr[indexWord(4, 3)] == 0); + + *z0Ptr = zPtr[indexWord(4, 2)]; + *z1Ptr = zPtr[indexWord(4, 1)]; + *z2Ptr = zPtr[indexWord(4, 0)]; +} + +/*---------------------------------------------------------------------------- +| 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'. +*----------------------------------------------------------------------------*/ + +static __inline void shortShift128Left(uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + *z1Ptr = a1<>((-count) & 63)); +} + +/*---------------------------------------------------------------------------- +| 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' 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'. +*----------------------------------------------------------------------------*/ + +static __inline void shortShift128Right(uint64_t a0, uint64_t a1, int count, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + uint64_t z0 = a0, z1 = a1; + int negCount = (-count) & 63; + + if (count != 0) { + z1 = (a0<>count); + z0 = a0>>count; + } + *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 uint64_t estimateDiv128To64(uint64_t a0, uint64_t a1, uint64_t b) +{ + uint128 term, rem; + uint64_t b0, b1; + uint64_t z; + if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF); + b0 = b>>32; + z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32; + term = softfloat_mul64To128(b, z); + rem = softfloat_sub128(a0, a1, term.v64, term.v0); + while (((int64_t) rem.v64) < 0) { + z -= UINT64_C(0x100000000); + b1 = b<<32; + rem = softfloat_add128(rem.v64, rem.v0, b0, b1); + } + rem.v64 = (rem.v64<<32) | (rem.v0>>32); + z |= (b0<<32 <= rem.v64) ? 0xFFFFFFFF : rem.v64 / b0; + return z; +} +#endif + +/*---------------------------------------------------------------------------- +| 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'. +*----------------------------------------------------------------------------*/ + +static __inline void add192(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t b0, uint64_t b1, uint64_t b2, uint64_t *z0Ptr, uint64_t *z1Ptr, uint64_t *z2Ptr) +{ + uint64_t 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 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'. +*----------------------------------------------------------------------------*/ + +static __inline void sub128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1, uint64_t *z0Ptr, uint64_t *z1Ptr) +{ + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - (a1 < b1); +} + +#endif diff --git a/src/cpu/softfloat3e/softfloat-specialize.c b/src/cpu/softfloat3e/softfloat-specialize.c new file mode 100644 index 0000000000..5bc57e565c --- /dev/null +++ b/src/cpu/softfloat3e/softfloat-specialize.c @@ -0,0 +1,90 @@ +/*============================================================================ +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#include "softfloat-specialize.h" + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +const int16_t int16_indefinite = (int16_t) 0x8000; +const int32_t int32_indefinite = (int32_t) 0x80000000; +const int64_t int64_indefinite = (int64_t) BX_CONST64(0x8000000000000000); + +const uint16_t uint16_indefinite = 0xffff; +const uint32_t uint32_indefinite = 0xffffffff; +const uint64_t uint64_indefinite = BX_CONST64(0xffffffffffffffff); + +/*---------------------------------------------------------------------------- +| Commonly used half-precision floating point constants +*----------------------------------------------------------------------------*/ +const float16 float16_negative_inf = 0xfc00; +const float16 float16_positive_inf = 0x7c00; +const float16 float16_negative_zero = 0x8000; +const float16 float16_positive_zero = 0x0000; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated half-precision NaN. +*----------------------------------------------------------------------------*/ +const float16 float16_default_nan = 0xFE00; + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const float32 float32_negative_inf = 0xff800000; +const float32 float32_positive_inf = 0x7f800000; +const float32 float32_negative_zero = 0x80000000; +const float32 float32_positive_zero = 0x00000000; +const float32 float32_negative_one = 0xbf800000; +const float32 float32_positive_one = 0x3f800000; +const float32 float32_max_float = 0x7f7fffff; +const float32 float32_min_float = 0xff7fffff; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +const float32 float32_default_nan = 0xffc00000; + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000); +const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000); +const float64 float64_negative_zero = BX_CONST64(0x8000000000000000); +const float64 float64_positive_zero = BX_CONST64(0x0000000000000000); +const float64 float64_negative_one = BX_CONST64(0xbff0000000000000); +const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000); +const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff); +const float64 float64_min_float = BX_CONST64(0xffefffffffffffff); + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000); diff --git a/src/cpu/softfloat3e/softfloat-specialize.h b/src/cpu/softfloat3e/softfloat-specialize.h new file mode 100644 index 0000000000..587f0d345b --- /dev/null +++ b/src/cpu/softfloat3e/softfloat-specialize.h @@ -0,0 +1,224 @@ +/*============================================================================ +This C source fragment is part of the SoftFloat IEC/IEEE Floating-point +Arithmetic Package, Release 2b. + +Written by John R. Hauser. This work was made possible in part by the +International Computer Science Institute, located at Suite 600, 1947 Center +Street, Berkeley, California 94704. Funding was partially provided by the +National Science Foundation under grant MIP-9311980. The original version +of this code was written as part of a project to build a fixed-point vector +processor in collaboration with the University of California at Berkeley, +overseen by Profs. Nelson Morgan and John Wawrzynek. More information +is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ +arithmetic/SoftFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has +been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES +RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS +AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, +COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE +EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE +INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR +OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) the source code for the derivative work includes prominent notice that +the work is derivative, and (2) the source code includes prominent notice with +these four paragraphs for those parts of this code that are retained. +=============================================================================*/ + +#ifndef _SOFTFLOAT_SPECIALIZE_H_ +#define _SOFTFLOAT_SPECIALIZE_H_ + +#include "config.h" +#include "softfloat.h" +#include "softfloat_types.h" + +/*============================================================================ + * Adapted for Bochs (x86 achitecture simulator) by + * Stanislav Shwartsman [sshwarts at sourceforge net] + * ==========================================================================*/ + +extern const int16_t int16_indefinite; +extern const int32_t int32_indefinite; +extern const int64_t int64_indefinite; + +extern const uint16_t uint16_indefinite; +extern const uint32_t uint32_indefinite; +extern const uint64_t uint64_indefinite; + +/*---------------------------------------------------------------------------- +| Commonly used half-precision floating point constants +*----------------------------------------------------------------------------*/ +extern const float16 float16_negative_inf; +extern const float16 float16_positive_inf; +extern const float16 float16_negative_zero; +extern const float16 float16_positive_zero; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated half-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float16 float16_default_nan; + +#define FLOAT16_EXP_BIAS 0xF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float16 packFloat16(int zSign, int zExp, uint16_t zSig) +{ + return (((uint16_t) zSign)<<15) + (((uint16_t) zExp)<<10) + zSig; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +extern const float32 float32_negative_inf; +extern const float32 float32_positive_inf; +extern const float32 float32_negative_zero; +extern const float32 float32_positive_zero; +extern const float32 float32_negative_one; +extern const float32 float32_positive_one; +extern const float32 float32_max_float; +extern const float32 float32_min_float; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated single-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float32 float32_default_nan; + +#define FLOAT32_EXP_BIAS 0x7F + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| single-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float32 packFloat32(int zSign, int16_t zExp, uint32_t zSig) +{ + return (((uint32_t) zSign)<<31) + (((uint32_t) zExp)<<23) + zSig; +} + +/*---------------------------------------------------------------------------- +| Commonly used single-precision floating point constants +*----------------------------------------------------------------------------*/ +extern const float64 float64_negative_inf; +extern const float64 float64_positive_inf; +extern const float64 float64_negative_zero; +extern const float64 float64_positive_zero; +extern const float64 float64_negative_one; +extern const float64 float64_positive_one; +extern const float64 float64_max_float; +extern const float64 float64_min_float; + +/*---------------------------------------------------------------------------- +| The pattern for a default generated double-precision NaN. +*----------------------------------------------------------------------------*/ +extern const float64 float64_default_nan; + +#define FLOAT64_EXP_BIAS 0x3FF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a +| double-precision floating-point value, returning the result. After being +| shifted into the proper positions, the three fields are simply added +| together to form the result. This means that any integer portion of `zSig' +| will be added into the exponent. Since a properly normalized significand +| will have an integer portion equal to 1, the `zExp' input should be 1 less +| than the desired result exponent whenever `zSig' is a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float64 packFloat64(int zSign, int16_t zExp, uint64_t zSig) +{ + return (((uint64_t) zSign)<<63) + (((uint64_t) zExp)<<52) + zSig; +} + +/*----------------------------------------------------------------------------- +| Commonly used extended double-precision floating-point constants. +*----------------------------------------------------------------------------*/ +extern const floatx80 Const_Z; +extern const floatx80 Const_1; +extern const floatx80 Const_L2T; +extern const floatx80 Const_L2E; +extern const floatx80 Const_PI; +extern const floatx80 Const_LG2; +extern const floatx80 Const_LN2; +extern const floatx80 Const_INF; +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. The +| `high' and `low' values hold the most- and least-significant bits, +| respectively. +*----------------------------------------------------------------------------*/ +#define floatx80_default_nan_exp 0xFFFF +#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000) + +#define FLOATX80_EXP_BIAS 0x3FFF + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an +| extended double-precision floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +static __inline floatx80 packFloatx80(int zSign, int32_t zExp, uint64_t zSig) +{ + floatx80 z; + z.signif = zSig; + z.signExp = (zSign << 15) + zExp; + return z; +} + +#ifdef FLOAT128 + +/*---------------------------------------------------------------------------- +| Packs the sign `zSign', the exponent `zExp', and the significand formed +| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision +| floating-point value, returning the result. After being shifted into the +| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply +| added together to form the most significant 32 bits of the result. This +| means that any integer portion of `zSig0' will be added into the exponent. +| Since a properly normalized significand will have an integer portion equal +| to 1, the `zExp' input should be 1 less than the desired result exponent +| whenever `zSig0' and `zSig1' concatenated form a complete, normalized +| significand. +*----------------------------------------------------------------------------*/ + +static __inline float128_t packFloat128(int zSign, int32_t zExp, uint64_t zSig0, uint64_t zSig1) +{ + float128_t z; + z.v0 = zSig1; + z.v64 = (((uint64_t) zSign)<<63) + (((uint64_t) zExp)<<48) + zSig0; + return z; +} + +/*---------------------------------------------------------------------------- +| Packs two 64-bit precision integers into into the quadruple-precision +| floating-point value, returning the result. +*----------------------------------------------------------------------------*/ + +static __inline float128_t packFloat128(uint64_t zHi, uint64_t zLo) +{ + float128_t z; + z.v0 = zLo; + z.v64 = zHi; + return z; +} + +#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo)) + +#endif +#endif diff --git a/src/cpu/softfloat3e/softfloat.h b/src/cpu/softfloat3e/softfloat.h new file mode 100644 index 0000000000..40253a2a94 --- /dev/null +++ b/src/cpu/softfloat3e/softfloat.h @@ -0,0 +1,702 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +/*============================================================================ +| Note: If SoftFloat is made available as a general library for programs to +| use, it is strongly recommended that a platform-specific version of this +| header, "softfloat.h", be created that folds in "softfloat_types.h" and that +| eliminates all dependencies on compile-time macros. +*============================================================================*/ + +#ifndef _SOFTFLOAT_H_ +#define _SOFTFLOAT_H_ + +#include + +#include "softfloat_types.h" +#include "softfloat-extra.h" + +struct softfloat_status_t +{ + uint8_t softfloat_roundingMode; + int softfloat_exceptionFlags; + int softfloat_exceptionMasks; + int softfloat_suppressException; + + bool softfloat_denormals_are_zeros; + bool softfloat_flush_underflow_to_zero; + + /*---------------------------------------------------------------------------- + | Rounding precision for 80-bit extended double-precision floating-point. + | Valid values are 32, 64, and 80. + *----------------------------------------------------------------------------*/ + uint8_t extF80_roundingPrecision; +}; + +/*---------------------------------------------------------------------------- +| Software floating-point rounding mode. +*----------------------------------------------------------------------------*/ +enum { + softfloat_round_near_even = 0, + softfloat_round_min = 1, + softfloat_round_down = softfloat_round_min, + softfloat_round_max = 2, + softfloat_round_up = softfloat_round_max, + softfloat_round_minMag = 3, + softfloat_round_to_zero = softfloat_round_minMag, + softfloat_round_near_maxMag = 4 +}; + +/*---------------------------------------------------------------------------- +| Software floating-point exception flags. +*----------------------------------------------------------------------------*/ +enum softfloat_exception_flag_t { + softfloat_flag_invalid = 0x01, + softfloat_flag_denormal = 0x02, + softfloat_flag_divbyzero = 0x04, + softfloat_flag_infinite = softfloat_flag_divbyzero, + softfloat_flag_overflow = 0x08, + softfloat_flag_underflow = 0x10, + softfloat_flag_inexact = 0x20 +}; + +static const unsigned softfloat_all_exceptions_mask = 0x3f; + +#define FLOATX80 + +#ifdef FLOATX80 +#define RAISE_SW_C1 0x0200 +#endif + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point ordering relations +*----------------------------------------------------------------------------*/ +enum { + softfloat_relation_less = -1, + softfloat_relation_equal = 0, + softfloat_relation_greater = 1, + softfloat_relation_unordered = 2 +}; + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point class. +*----------------------------------------------------------------------------*/ +typedef enum { + softfloat_zero, + softfloat_SNaN, + softfloat_QNaN, + softfloat_negative_inf, + softfloat_positive_inf, + softfloat_denormal, + softfloat_normalized +} softfloat_class_t; + +/*---------------------------------------------------------------------------- +| Options to indicate which negations to perform in f*_muladd() +| Using these differs from negating an input or output before calling +| the muladd function in that this means that a NaN doesn't have its +| sign bit inverted before it is propagated. +*----------------------------------------------------------------------------*/ +enum { + softfloat_mulAdd_subC = 1, + softfloat_muladd_negate_c = softfloat_mulAdd_subC, + softfloat_mulAdd_subProd = 2, + softfloat_muladd_negate_product = softfloat_mulAdd_subProd, + softfloat_muladd_negate_result = softfloat_muladd_negate_c | softfloat_muladd_negate_product +}; + +static __inline void softfloat_setFlags(struct softfloat_status_t *status, int flags) { + status->softfloat_exceptionFlags = flags; +} + +/*---------------------------------------------------------------------------- +| Routine to raise any or all of the software floating-point exception flags. +*----------------------------------------------------------------------------*/ +static __inline void softfloat_raiseFlags(struct softfloat_status_t *status, int flags) { + status->softfloat_exceptionFlags |= flags; +} + +/*---------------------------------------------------------------------------- +| Check if exception is masked. +*----------------------------------------------------------------------------*/ +static __inline int softfloat_isMaskedException(const struct softfloat_status_t *status, int flags) { + return status->softfloat_exceptionMasks & flags; +} + +/*---------------------------------------------------------------------------- +| Suppress generation of these exceptions. +*----------------------------------------------------------------------------*/ +static __inline void softfloat_suppressException(struct softfloat_status_t *status, int flags) { + status->softfloat_suppressException |= flags; +} + +/*---------------------------------------------------------------------------- +| Obtain current rounding mode. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_getRoundingMode(const struct softfloat_status_t *status) { + return status->softfloat_roundingMode; +} + +/*---------------------------------------------------------------------------- +| Read denormals-are-zeroes flag. +*----------------------------------------------------------------------------*/ +static __inline bool softfloat_denormalsAreZeros(const struct softfloat_status_t *status) { + return status->softfloat_denormals_are_zeros; +} + +/*---------------------------------------------------------------------------- +| Read flush-underflow-to-zero flag. +*----------------------------------------------------------------------------*/ +static __inline bool softfloat_flushUnderflowToZero(const struct softfloat_status_t *status) { + return status->softfloat_flush_underflow_to_zero; +} + +/*---------------------------------------------------------------------------- +| Obtain current rounding precision for F80. +*----------------------------------------------------------------------------*/ +static __inline uint8_t softfloat_extF80_roundingPrecision(const struct softfloat_status_t *status) { + return status->extF80_roundingPrecision; +} + +/*---------------------------------------------------------------------------- +| Returns raised IEC/IEEE floating-point exception flags. +*----------------------------------------------------------------------------*/ +static __inline int softfloat_getExceptionFlags(const struct softfloat_status_t *status) { + return status->softfloat_exceptionFlags & ~status->softfloat_suppressException; +} + +/*---------------------------------------------------------------------------- +| Raise floating point precision lost up flag (floatx80 only). +*----------------------------------------------------------------------------*/ +#ifdef FLOATX80 +static __inline void softfloat_setRoundingUp(struct softfloat_status_t *status) { + status->softfloat_exceptionFlags |= RAISE_SW_C1; +} +#endif + +/*---------------------------------------------------------------------------- +| Integer-to-floating-point conversion routines. +*----------------------------------------------------------------------------*/ +float16 ui32_to_f16(uint32_t, struct softfloat_status_t *); +float32 ui32_to_f32(uint32_t, struct softfloat_status_t *); +float64 ui32_to_f64(uint32_t); +float16 ui64_to_f16(uint64_t, struct softfloat_status_t *); +float32 ui64_to_f32(uint64_t, struct softfloat_status_t *); +float64 ui64_to_f64(uint64_t, struct softfloat_status_t *); +float16 i32_to_f16(int32_t, struct softfloat_status_t *); +float32 i32_to_f32(int32_t, struct softfloat_status_t *); +float64 i32_to_f64(int32_t); +float16 i64_to_f16(int64_t, struct softfloat_status_t *); +float32 i64_to_f32(int64_t, struct softfloat_status_t *); +float64 i64_to_f64(int64_t, struct softfloat_status_t *); + +static __inline float16 i16_to_f16(int16_t a, struct softfloat_status_t *status) { + return i32_to_f16((int32_t)(a), status); +} + +static __inline float16 ui16_to_f16(uint16_t a, struct softfloat_status_t *status) { + return ui32_to_f16((uint32_t)(a), status); +} + +/*---------------------------------------------------------------------------- +| 16-bit (half-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint32_t f16_to_ui32(float16, uint8_t, bool, struct softfloat_status_t *); +uint64_t f16_to_ui64(float16, uint8_t, bool, struct softfloat_status_t *); +int32_t f16_to_i32(float16, uint8_t, bool, struct softfloat_status_t *); +int64_t f16_to_i64(float16, uint8_t, bool, struct softfloat_status_t *); +uint32_t f16_to_ui32_r_minMag(float16, bool, struct softfloat_status_t *); +uint64_t f16_to_ui64_r_minMag(float16, bool, struct softfloat_status_t *); +int32_t f16_to_i32_r_minMag(float16, bool, struct softfloat_status_t *); +int64_t f16_to_i64_r_minMag(float16, bool, struct softfloat_status_t *); +float32 f16_to_f32(float16, struct softfloat_status_t *); +float64 f16_to_f64(float16, struct softfloat_status_t *); +float16 f16_roundToInt(float16, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float16 f16_add(float16, float16, struct softfloat_status_t *); +float16 f16_sub(float16, float16, struct softfloat_status_t *); +float16 f16_mul(float16, float16, struct softfloat_status_t *); +float16 f16_mulAdd(float16, float16, float16, uint8_t op, struct softfloat_status_t *); +float16 f16_div(float16, float16, struct softfloat_status_t *); +float16 f16_min(float16, float16, struct softfloat_status_t *); +float16 f16_max(float16, float16, struct softfloat_status_t *); +float16 f16_getExp(float16, struct softfloat_status_t *); +float16 f16_getMant(float16, struct softfloat_status_t *, int, int); +float16 f16_range(float16, float16, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *); +int f16_compare(float16, float16, bool, struct softfloat_status_t *); +float16 f16_sqrt(float16, struct softfloat_status_t *); +softfloat_class_t f16_class(float16); + +#ifdef __cplusplus +extern "C" { +#endif +bool f16_isSignalingNaN(float16); +bool f16_isNaN(float16); +#ifdef __cplusplus +} +#endif + +bool f16_sign(float16); +int8_t f16_exp(float16); +uint16_t f16_fraction(float16); +float16 f16_denormal_to_zero(float16); + +static __inline int f16_compare_normal(float16 a, float16 b, struct softfloat_status_t *status) { + return f16_compare(a, b, 0, status); +} + +static __inline int f16_compare_quiet(float16 a, float16 b, struct softfloat_status_t *status) { + return f16_compare(a, b, 1, status); +} + +static __inline float16 f16_roundToInt_normal(float16 a, uint8_t scale, struct softfloat_status_t *status) { + return f16_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); +} +static __inline float16 f16_roundToInt_noscale(float16 a, struct softfloat_status_t *status) { + return f16_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); +} + +static __inline int64_t f16_to_i64_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_i64(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int32_t f16_to_i32_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_i32(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int16_t f16_to_i16(float16 a, struct softfloat_status_t *status) +{ + int32_t val_32 = f16_to_i32_normal(a, status); + int16_t val_16 = (int16_t) val_32; + if ((int32_t)(val_16) != val_32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return val_16; +} + +static __inline int64_t f16_to_i64_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_i64_r_minMag(a, true, status); +} +static __inline int32_t f16_to_i32_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_i32_r_minMag(a, true, status); +} + +static __inline int16_t f16_to_i16_round_to_zero(float16 a, struct softfloat_status_t *status) +{ + int32_t val_32 = f16_to_i32_round_to_zero(a, status); + int16_t val_16 = (int16_t) val_32; + if ((int32_t)(val_16) != val_32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return val_16; +} + +static __inline uint64_t f16_to_ui64_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_ui64(a, softfloat_getRoundingMode(status), true, status); +} +static __inline uint32_t f16_to_ui32_normal(float16 a, struct softfloat_status_t *status) { + return f16_to_ui32(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline uint16_t f16_to_ui16(float16 a, struct softfloat_status_t *status) +{ + uint32_t val_32 = f16_to_ui32_normal(a, status); + if (val_32 > 0xFFFF) { + softfloat_setFlags(status, softfloat_flag_invalid); + return 0xFFFF; + } + return (uint16_t) val_32; +} + +static __inline uint64_t f16_to_ui64_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_ui64_r_minMag(a, true, status); +} +static __inline uint32_t f16_to_ui32_round_to_zero(float16 a, struct softfloat_status_t *status) { + return f16_to_ui32_r_minMag(a, true, status); +} + +static __inline uint16_t f16_to_ui16_round_to_zero(float16 a, struct softfloat_status_t *status) +{ + uint32_t val_32 = f16_to_ui32_round_to_zero(a, status); + if (val_32 > 0xFFFF) { + softfloat_setFlags(status, softfloat_flag_invalid); + return 0xFFFF; + } + return (uint16_t) val_32; +} + +static __inline float16 f16_fmadd(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, 0, status); +} +static __inline float16 f16_fmsub(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, softfloat_muladd_negate_c, status); +} +static __inline float16 f16_fnmadd(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, softfloat_muladd_negate_product, status); +} +static __inline float16 f16_fnmsub(float16 a, float16 b, float16 c, struct softfloat_status_t *status) { + return f16_mulAdd(a, b, c, softfloat_muladd_negate_result, status); +} + +/*---------------------------------------------------------------------------- +| 32-bit (single-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint32_t f32_to_ui32(float32, uint8_t, bool, struct softfloat_status_t *); +uint64_t f32_to_ui64(float32, uint8_t, bool, struct softfloat_status_t *); +int32_t f32_to_i32(float32, uint8_t, bool, struct softfloat_status_t *); +int64_t f32_to_i64(float32, uint8_t, bool, struct softfloat_status_t *); +uint32_t f32_to_ui32_r_minMag(float32, bool, struct softfloat_status_t *); +uint64_t f32_to_ui64_r_minMag(float32, bool, struct softfloat_status_t *); +int32_t f32_to_i32_r_minMag(float32, bool, struct softfloat_status_t *); +int64_t f32_to_i64_r_minMag(float32, bool, struct softfloat_status_t *); +float16 f32_to_f16(float32, struct softfloat_status_t *); +float64 f32_to_f64(float32, struct softfloat_status_t *); +float32 f32_roundToInt(float32, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float32 f32_add(float32, float32, struct softfloat_status_t *); +float32 f32_sub(float32, float32, struct softfloat_status_t *); +float32 f32_mul(float32, float32, struct softfloat_status_t *); +float32 f32_mulAdd(float32, float32, float32, uint8_t op, struct softfloat_status_t *); +float32 f32_div(float32, float32, struct softfloat_status_t *); +float32 f32_min(float32, float32, struct softfloat_status_t *); +float32 f32_max(float32, float32, struct softfloat_status_t *); +float32 f32_scalef(float32, float32, struct softfloat_status_t *); +float32 f32_getExp(float32, struct softfloat_status_t *); +float32 f32_getMant(float32, struct softfloat_status_t *, int, int); +float32 f32_range(float32, float32, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *); +float32 f32_frc(float32, struct softfloat_status_t *); +int f32_compare(float32, float32, bool, struct softfloat_status_t *); +float32 f32_sqrt(float32, struct softfloat_status_t *); +softfloat_class_t f32_class(float32); + +#ifdef __cplusplus +extern "C" { +#endif +bool f32_isSignalingNaN(float32); +bool f32_isNaN(float32); +#ifdef __cplusplus +} +#endif + +bool f32_sign(float32); +int16_t f32_exp(float32); +uint32_t f32_fraction(float32); +float32 f32_denormal_to_zero(float32); + +static __inline int f32_compare_normal(float32 a, float32 b, struct softfloat_status_t *status) { + return f32_compare(a, b, 0, status); +} + +static __inline int f32_compare_quiet(float32 a, float32 b, struct softfloat_status_t *status) { + return f32_compare(a, b, 1, status); +} + +static __inline float32 f32_roundToInt_normal(float32 a, uint8_t scale, struct softfloat_status_t *status) { + return f32_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); +} +static __inline float32 f32_roundToInt_noscale(float32 a, struct softfloat_status_t *status) { + return f32_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f32_to_i32_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_i32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int64_t f32_to_i64_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_i64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f32_to_i32_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_i32_r_minMag(a, true, status); +} +static __inline int64_t f32_to_i64_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_i64_r_minMag(a, true, status); +} + +static __inline uint32_t f32_to_ui32_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_ui32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline uint64_t f32_to_ui64_normal(float32 a, struct softfloat_status_t *status) { + return f32_to_ui64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline uint32_t f32_to_ui32_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_ui32_r_minMag(a, true, status); +} +static __inline uint64_t f32_to_ui64_round_to_zero(float32 a, struct softfloat_status_t *status) { + return f32_to_ui64_r_minMag(a, true, status); +} + +static __inline float32 f32_fmadd(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, 0, status); +} +static __inline float32 f32_fmsub(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, softfloat_muladd_negate_c, status); +} +static __inline float32 f32_fnmadd(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, softfloat_muladd_negate_product, status); +} +static __inline float32 f32_fnmsub(float32 a, float32 b, float32 c, struct softfloat_status_t *status) { + return f32_mulAdd(a, b, c, softfloat_muladd_negate_result, status); +} + +/*---------------------------------------------------------------------------- +| 64-bit (double-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +uint32_t f64_to_ui32(float64, uint8_t, bool, struct softfloat_status_t *); +uint64_t f64_to_ui64(float64, uint8_t, bool, struct softfloat_status_t *); +int32_t f64_to_i32(float64, uint8_t, bool, struct softfloat_status_t *); +int64_t f64_to_i64(float64, uint8_t, bool, struct softfloat_status_t *); +uint32_t f64_to_ui32_r_minMag(float64, bool, struct softfloat_status_t *); +uint64_t f64_to_ui64_r_minMag(float64, bool, struct softfloat_status_t *); +int32_t f64_to_i32_r_minMag(float64, bool, struct softfloat_status_t *); +int64_t f64_to_i64_r_minMag(float64, bool, struct softfloat_status_t *); +float16 f64_to_f16(float64, struct softfloat_status_t *); +float32 f64_to_f32(float64, struct softfloat_status_t *); +float64 f64_roundToInt(float64, uint8_t, uint8_t, bool, struct softfloat_status_t *); +float64 f64_add(float64, float64, struct softfloat_status_t *); +float64 f64_sub(float64, float64, struct softfloat_status_t *); +float64 f64_mul(float64, float64, struct softfloat_status_t *); +float64 f64_mulAdd(float64, float64, float64, uint8_t op, struct softfloat_status_t *); +float64 f64_div(float64, float64, struct softfloat_status_t *); +float64 f64_min(float64, float64, struct softfloat_status_t *); +float64 f64_max(float64, float64, struct softfloat_status_t *); +float64 f64_scalef(float64, float64, struct softfloat_status_t *); +float64 f64_getExp(float64, struct softfloat_status_t *); +float64 f64_getMant(float64, struct softfloat_status_t *, int, int); +float64 f64_range(float64, float64, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *); +float64 f64_frc(float64, struct softfloat_status_t *); +int f64_compare(float64, float64, bool, struct softfloat_status_t *); +float64 f64_sqrt(float64, struct softfloat_status_t *); +softfloat_class_t f64_class(float64); + +#ifdef __cplusplus +extern "C" { +#endif +bool f64_isSignalingNaN(float64); +bool f64_isNaN(float64); +#ifdef __cplusplus +} +#endif + +bool f64_sign(float64); +int16_t f64_exp(float64); +uint64_t f64_fraction(float64); +float64 f64_denormal_to_zero(float64); + +static __inline int f64_compare_normal(float64 a, float64 b, struct softfloat_status_t *status) { + return f64_compare(a, b, 0, status); +} + +static __inline int f64_compare_quiet(float64 a, float64 b, struct softfloat_status_t *status) { + return f64_compare(a, b, 1, status); +} + +static __inline float64 f64_roundToInt_normal(float64 a, uint8_t scale, struct softfloat_status_t *status) { + return f64_roundToInt(a, scale, softfloat_getRoundingMode(status), true, status); +} +static __inline float64 f64_roundToInt_noscale(float64 a, struct softfloat_status_t *status) { + return f64_roundToInt(a, 0, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f64_to_i32_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_i32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int64_t f64_to_i64_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_i64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int32_t f64_to_i32_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_i32_r_minMag(a, true, status); +} +static __inline int64_t f64_to_i64_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_i64_r_minMag(a, true, status); +} + +static __inline uint32_t f64_to_ui32_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_ui32(a, softfloat_getRoundingMode(status), true, status); +} +static __inline uint64_t f64_to_ui64_normal(float64 a, struct softfloat_status_t *status) { + return f64_to_ui64(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline uint32_t f64_to_ui32_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_ui32_r_minMag(a, true, status); +} +static __inline uint64_t f64_to_ui64_round_to_zero(float64 a, struct softfloat_status_t *status) { + return f64_to_ui64_r_minMag(a, true, status); +} + +static __inline float64 f64_fmadd(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, 0, status); +} +static __inline float64 f64_fmsub(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, softfloat_muladd_negate_c, status); +} +static __inline float64 f64_fnmadd(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, softfloat_muladd_negate_product, status); +} +static __inline float64 f64_fnmsub(float64 a, float64 b, float64 c, struct softfloat_status_t *status) { + return f64_mulAdd(a, b, c, softfloat_muladd_negate_result, status); +} + +#ifdef __cplusplus +extern "C" { +#endif +/*---------------------------------------------------------------------------- +| 80-bit extended double-precision floating-point operations. +*----------------------------------------------------------------------------*/ +extFloat80_t f16_to_extF80(float16, struct softfloat_status_t *); +extFloat80_t f32_to_extF80(float32, struct softfloat_status_t *); +extFloat80_t f64_to_extF80(float64, struct softfloat_status_t *); +extFloat80_t i32_to_extF80(int32_t); +extFloat80_t i64_to_extF80(int64_t); +extFloat80_t ui32_to_extF80(uint32_t); +extFloat80_t ui64_to_extF80(uint64_t); + +uint32_t extF80_to_ui32(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t extF80_to_ui64(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +int32_t extF80_to_i32(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +int64_t extF80_to_i64(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +uint32_t extF80_to_ui32_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +uint64_t extF80_to_ui64_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +int32_t extF80_to_i32_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +int64_t extF80_to_i64_r_minMag(extFloat80_t, bool, struct softfloat_status_t *); +float16 extF80_to_f16(extFloat80_t, struct softfloat_status_t *); +float32 extF80_to_f32(extFloat80_t, struct softfloat_status_t *); +float64 extF80_to_f64(extFloat80_t, struct softfloat_status_t *); +float128_t extF80_to_f128(extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_roundToInt(extFloat80_t, uint8_t, bool, struct softfloat_status_t *); +extFloat80_t extF80_add(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_sub(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_mul(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_div(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_rem(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_scale(extFloat80_t, extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_sqrt(extFloat80_t, struct softfloat_status_t *); +extFloat80_t extF80_extract(extFloat80_t *, struct softfloat_status_t *); +int extF80_compare(extFloat80_t, extFloat80_t, int, struct softfloat_status_t *); +softfloat_class_t extF80_class(extFloat80_t); + +static __inline int extF80_compare_normal(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) { + return extF80_compare(a, b, 0, status); +} + +static __inline int extF80_compare_quiet(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status) { + return extF80_compare(a, b, 1, status); +} + +static __inline extFloat80_t extF80_roundToInt_normal(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_roundToInt(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int64_t extF80_to_i64_normal(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i64(a, softfloat_getRoundingMode(status), true, status); +} +static __inline int32_t extF80_to_i32_normal(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i32(a, softfloat_getRoundingMode(status), true, status); +} + +static __inline int16_t extF80_to_i16(extFloat80_t a, struct softfloat_status_t *status) +{ + int32_t v32 = extF80_to_i32_normal(a, status); + int16_t v16 = (int16_t) v32; + + if ((int32_t)(v16) != v32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return v16; +} + +static __inline int64_t extF80_to_i64_round_to_zero(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i64_r_minMag(a, true, status); +} +static __inline int32_t extF80_to_i32_round_to_zero(extFloat80_t a, struct softfloat_status_t *status) { + return extF80_to_i32_r_minMag(a, true, status); +} + +static __inline int16_t extF80_to_i16_round_to_zero(extFloat80_t a, struct softfloat_status_t *status) +{ + int32_t v32 = extF80_to_i32_round_to_zero(a, status); + int16_t v16 = (int16_t) v32; + + if ((int32_t)(v16) != v32) { + softfloat_setFlags(status, softfloat_flag_invalid); + return (int16_t) 0x8000; + } + return v16; +} + +bool extF80_isUnsupported(extFloat80_t); +bool extF80_isSignalingNaN(extFloat80_t); +bool extF80_isNaN(extFloat80_t); + +bool extF80_sign(extFloat80_t); +int16_t extF80_exp(extFloat80_t); +uint64_t extF80_fraction(extFloat80_t); + +/*---------------------------------------------------------------------------- +| 128-bit (quadruple-precision) floating-point operations. +*----------------------------------------------------------------------------*/ +float128_t f32_to_f128(float32, struct softfloat_status_t *); +float128_t f64_to_f128(float64, struct softfloat_status_t *); +float128_t i32_to_f128(int32_t); +float128_t i64_to_f128(int64_t); +float128_t ui32_to_f128(uint32_t); +float128_t ui64_to_f128(uint64_t); + +uint32_t f128_to_ui32(float128_t, uint8_t, bool, struct softfloat_status_t *); +uint64_t f128_to_ui64(float128_t, uint8_t, bool, struct softfloat_status_t *); +int32_t f128_to_i32(float128_t, uint8_t, bool, struct softfloat_status_t *); +int64_t f128_to_i64(float128_t, uint8_t, bool, struct softfloat_status_t *); +uint32_t f128_to_ui32_r_minMag(float128_t, bool, struct softfloat_status_t *); +uint64_t f128_to_ui64_r_minMag(float128_t, bool, struct softfloat_status_t *); +int32_t f128_to_i32_r_minMag(float128_t, bool, struct softfloat_status_t *); +int64_t f128_to_i64_r_minMag(float128_t, bool, struct softfloat_status_t *); +float32 f128_to_f32(float128_t, struct softfloat_status_t *); +float64 f128_to_f64(float128_t, struct softfloat_status_t *); +extFloat80_t f128_to_extF80(float128_t, struct softfloat_status_t *); +float128_t f128_roundToInt(float128_t, uint8_t, bool, struct softfloat_status_t *); +float128_t f128_add(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_sub(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_mul(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_mulAdd(float128_t, float128_t, float128_t, uint8_t op, struct softfloat_status_t *); +float128_t f128_div(float128_t, float128_t, struct softfloat_status_t *); +float128_t f128_sqrt(float128_t, struct softfloat_status_t *); +bool f128_isSignalingNaN(float128_t); +bool f128_isNaN(float128_t); +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/cpu/softfloat3e/softfloat_types.h b/src/cpu/softfloat3e/softfloat_types.h new file mode 100644 index 0000000000..001f8e0c69 --- /dev/null +++ b/src/cpu/softfloat3e/softfloat_types.h @@ -0,0 +1,87 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _SOFTFLOAT_TYPES_H_ +#define _SOFTFLOAT_TYPES_H_ + +#include + +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point types. +*----------------------------------------------------------------------------*/ +typedef uint16_t float16, bfloat16; +typedef uint32_t float32; +typedef uint64_t float64; + +struct uint128 { uint64_t v0, v64; }; +struct uint64_extra { uint64_t extra, v; }; +struct uint128_extra { uint64_t extra; struct uint128 v; }; + +/*---------------------------------------------------------------------------- +| Types used to pass 16-bit, 32-bit, 64-bit, and 128-bit floating-point +| arguments and results to/from functions. These types must be exactly +| 16 bits, 32 bits, 64 bits, and 128 bits in size, respectively. +*----------------------------------------------------------------------------*/ +typedef struct f16_t { uint16_t v; } float16_t; +typedef struct f32_t { uint32_t v; } float32_t; +typedef struct f64_t { uint64_t v; } float64_t; +typedef struct uint128 float128_t; + +/*---------------------------------------------------------------------------- +| The format of an 80-bit extended floating-point number in memory. This +| structure must contain a 16-bit field named 'signExp' and a 64-bit field +| named 'signif'. +*----------------------------------------------------------------------------*/ + +struct extFloat80M { + uint64_t signif; + uint16_t signExp; +}; + +/*---------------------------------------------------------------------------- +| The type used to pass 80-bit extended floating-point arguments and +| results to/from functions. This type must have size identical to +| 'struct extFloat80M'. Type 'extFloat80_t' can be defined as an alias for +| 'struct extFloat80M'. Alternatively, if a platform has "native" support +| for IEEE-Standard 80-bit extended floating-point, it may be possible, +| if desired, to define 'extFloat80_t' as an alias for the native type +| (presumably either 'long double' or a nonstandard compiler-intrinsic type). +| In that case, the 'signif' and 'signExp' fields of 'struct extFloat80M' +| must align exactly with the locations in memory of the sign, exponent, and +| significand of the native type. +*----------------------------------------------------------------------------*/ +typedef struct extFloat80M extFloat80_t, floatx80; + +#endif diff --git a/src/cpu/softfloat3e/specialize.h b/src/cpu/softfloat3e/specialize.h new file mode 100644 index 0000000000..90d4a2caac --- /dev/null +++ b/src/cpu/softfloat3e/specialize.h @@ -0,0 +1,280 @@ +/*============================================================================ + +This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#ifndef _SPECIALIZE_H_ +#define _SPECIALIZE_H_ + +#include +#include +#include "softfloat.h" + +/*---------------------------------------------------------------------------- +| The values to return on conversions to 32-bit integer formats that raise an +| invalid exception. +*----------------------------------------------------------------------------*/ +#define ui32_fromPosOverflow 0xFFFFFFFF +#define ui32_fromNegOverflow 0xFFFFFFFF +#define ui32_fromNaN 0xFFFFFFFF +#define i32_fromPosOverflow (-0x7FFFFFFF - 1) +#define i32_fromNegOverflow (-0x7FFFFFFF - 1) +#define i32_fromNaN (-0x7FFFFFFF - 1) + +/*---------------------------------------------------------------------------- +| The values to return on conversions to 64-bit integer formats that raise an +| invalid exception. +*----------------------------------------------------------------------------*/ +#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF) +#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF) +#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) +#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1) + +/*---------------------------------------------------------------------------- +| "Common NaN" structure, used to transfer NaN representations from one format +| to another. +*----------------------------------------------------------------------------*/ +struct commonNaN { + bool sign; + uint64_t v0, v64; +}; + + +#ifdef __cplusplus +extern "C" { +#endif +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 16-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF16UI 0xFE00 + +/*---------------------------------------------------------------------------- +| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a +| 16-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF16UI(uiA) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f16UIToCommonNaN(uint16_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint16_t softfloat_commonNaNToF16UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint16_t + softfloat_propagateNaNF16UI(uint16_t uiA, uint16_t uiB, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 32-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF32UI 0xFFC00000 + +/*---------------------------------------------------------------------------- +| Returns true when 32-bit unsigned integer 'uiA' has the bit pattern of a +| 32-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF32UI(uiA) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF)) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f32UIToCommonNaN(uint32_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint32_t softfloat_commonNaNToF32UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint32_t + softfloat_propagateNaNF32UI(uint32_t uiA, uint32_t uiB, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 64-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF64UI UINT64_C(0xFFF8000000000000) + +/*---------------------------------------------------------------------------- +| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a +| 64-bit floating-point signaling NaN. +| Note: This macro evaluates its argument more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF64UI(uiA) ((((uiA) & UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA) & UINT64_C(0x0007FFFFFFFFFFFF))) + +/*---------------------------------------------------------------------------- +| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f64UIToCommonNaN(uint64_t uiA, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +uint64_t softfloat_commonNaNToF64UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating- +| point values, at least one of which is a NaN, returns the bit pattern of +| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a +| signaling NaN, the invalid exception is raised. +*----------------------------------------------------------------------------*/ +uint64_t + softfloat_propagateNaNF64UI(uint64_t uiA, uint64_t uiB, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 80-bit extended floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNExtF80UI64 0xFFFF +#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000) + +/*---------------------------------------------------------------------------- +| Returns true when the 80-bit unsigned integer formed from concatenating +| 16-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of an 80-bit extended +| floating-point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C(0x4000000000000000)) && ((uiA0) & UINT64_C(0x3FFFFFFFFFFFFFFF))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' +| has the bit pattern of an 80-bit extended floating-point NaN, converts +| this NaN to the common NaN form, and stores the resulting common NaN at the +| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +void softfloat_extF80UIToCommonNaN(uint16_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended +| floating-point NaN, and returns the bit pattern of this value as an unsigned +| integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN *aPtr); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting +| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 80-bit extended floating-point value, and assuming at least on of these +| floating-point values is a NaN, returns the bit pattern of the combined NaN +| result. If either original floating-point value is a signaling NaN, the +| invalid exception is raised. +*----------------------------------------------------------------------------*/ +extFloat80_t + softfloat_propagateNaNExtF80UI( + uint16_t uiA64, + uint64_t uiA0, + uint16_t uiB64, + uint64_t uiB0, + struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| The bit pattern for a default generated 128-bit floating-point NaN. +*----------------------------------------------------------------------------*/ +#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000) +#define defaultNaNF128UI0 UINT64_C(0) + +/*---------------------------------------------------------------------------- +| Returns true when the 128-bit unsigned integer formed from concatenating +| 64-bit 'uiA64' and 64-bit 'uiA0' has the bit pattern of a 128-bit floating- +| point signaling NaN. +| Note: This macro evaluates its arguments more than once. +*----------------------------------------------------------------------------*/ +#define softfloat_isSigNaNF128UI(uiA64, uiA0) ((((uiA64) & UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64) & UINT64_C(0x00007FFFFFFFFFFF)))) + +/*---------------------------------------------------------------------------- +| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0' +| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to +| the common NaN form, and stores the resulting common NaN at the location +| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception +| is raised. +*----------------------------------------------------------------------------*/ +void softfloat_f128UIToCommonNaN(uint64_t uiA64, uint64_t uiA0, struct commonNaN *zPtr, struct softfloat_status_t *status); + +/*---------------------------------------------------------------------------- +| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point +| NaN, and returns the bit pattern of this value as an unsigned integer. +*----------------------------------------------------------------------------*/ +struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN *); + +/*---------------------------------------------------------------------------- +| Interpreting the unsigned integer formed from concatenating 'uiA64' and +| 'uiA0' as a 128-bit floating-point value, and likewise interpreting the +| unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another +| 128-bit floating-point value, and assuming at least on of these floating- +| point values is a NaN, returns the bit pattern of the combined NaN result. +| If either original floating-point value is a signaling NaN, the invalid +| exception is raised. +*----------------------------------------------------------------------------*/ +struct uint128 + softfloat_propagateNaNF128UI( + uint64_t uiA64, + uint64_t uiA0, + uint64_t uiB64, + uint64_t uiB0, + struct softfloat_status_t *status +); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cpu/softfloat3e/ui32_to_extF80.cc b/src/cpu/softfloat3e/ui32_to_extF80.cc new file mode 100644 index 0000000000..80c6d86b01 --- /dev/null +++ b/src/cpu/softfloat3e/ui32_to_extF80.cc @@ -0,0 +1,56 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t ui32_to_extF80(uint32_t a) +{ + uint16_t uiZ64; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + if (a) { + shiftDist = softfloat_countLeadingZeros32(a); + uiZ64 = 0x401E - shiftDist; + a <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = (uint64_t) a<<32; + return z; +} diff --git a/src/cpu/softfloat3e/ui32_to_f128.cc b/src/cpu/softfloat3e/ui32_to_f128.cc new file mode 100644 index 0000000000..6ef8214a8c --- /dev/null +++ b/src/cpu/softfloat3e/ui32_to_f128.cc @@ -0,0 +1,55 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t ui32_to_f128(uint32_t a) +{ + uint64_t uiZ64; + int8_t shiftDist; + float128_t z; + + uiZ64 = 0; + if (a) { + shiftDist = softfloat_countLeadingZeros32(a) + 17; + uiZ64 = packToF128UI64(0, 0x402E - shiftDist, (uint64_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 ui32_to_f16(uint32_t a, struct softfloat_status_t *status) +{ + int8_t shiftDist; + uint16_t sig; + + shiftDist = softfloat_countLeadingZeros32(a) - 21; + if (0 <= shiftDist) { + return a ? packToF16UI(0, 0x18 - shiftDist, (uint16_t) a<>(-shiftDist) | ((uint32_t) (a<<(shiftDist & 31)) != 0) + : (uint16_t) a< +#include "internals.h" +#include "softfloat.h" + +float32 ui32_to_f32(uint32_t a, struct softfloat_status_t *status) +{ + if (! a) { + return 0; + } + if (a & 0x80000000) { + return softfloat_roundPackToF32(0, 0x9D, a>>1 | (a & 1), status); + } else { + return softfloat_normRoundPackToF32(0, 0x9C, a, status); + } +} diff --git a/src/cpu/softfloat3e/ui32_to_f64.c b/src/cpu/softfloat3e/ui32_to_f64.c new file mode 100644 index 0000000000..524d64eedf --- /dev/null +++ b/src/cpu/softfloat3e/ui32_to_f64.c @@ -0,0 +1,49 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 ui32_to_f64(uint32_t a) +{ + if (! a) { + return 0; + } else { + int8_t shiftDist = softfloat_countLeadingZeros32(a) + 21; + return packToF64UI(0, 0x432 - shiftDist, (uint64_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +extFloat80_t ui64_to_extF80(uint64_t a) +{ + uint16_t uiZ64; + int8_t shiftDist; + extFloat80_t z; + + uiZ64 = 0; + if (a) { + shiftDist = softfloat_countLeadingZeros64(a); + uiZ64 = 0x403E - shiftDist; + a <<= shiftDist; + } + z.signExp = uiZ64; + z.signif = a; + return z; +} diff --git a/src/cpu/softfloat3e/ui64_to_f128.cc b/src/cpu/softfloat3e/ui64_to_f128.cc new file mode 100644 index 0000000000..91be29f375 --- /dev/null +++ b/src/cpu/softfloat3e/ui64_to_f128.cc @@ -0,0 +1,65 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float128_t ui64_to_f128(uint64_t a) +{ + uint64_t uiZ64, uiZ0; + int8_t shiftDist; + struct uint128 zSig; + float128_t z; + + if (! a) { + uiZ64 = 0; + uiZ0 = 0; + } else { + shiftDist = softfloat_countLeadingZeros64(a) + 49; + if (64 <= shiftDist) { + zSig.v64 = a<<(shiftDist - 64); + zSig.v0 = 0; + } else { + zSig = softfloat_shortShiftLeft128(0, a, shiftDist); + } + uiZ64 = packToF128UI64(0, 0x406E - shiftDist, zSig.v64); + uiZ0 = zSig.v0; + } + z.v64 = uiZ64; + z.v0 = uiZ0; + return z; +} diff --git a/src/cpu/softfloat3e/ui64_to_f16.c b/src/cpu/softfloat3e/ui64_to_f16.c new file mode 100644 index 0000000000..f2339e905a --- /dev/null +++ b/src/cpu/softfloat3e/ui64_to_f16.c @@ -0,0 +1,55 @@ +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3e, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All Rights Reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float16 ui64_to_f16(uint64_t a, struct softfloat_status_t *status) +{ + int8_t shiftDist; + uint16_t sig; + + shiftDist = softfloat_countLeadingZeros64(a) - 53; + if (0 <= shiftDist) { + return a ? packToF16UI(0, 0x18 - shiftDist, (uint16_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float32 ui64_to_f32(uint64_t a, struct softfloat_status_t *status) +{ + int8_t shiftDist; + uint32_t sig; + + shiftDist = softfloat_countLeadingZeros64(a) - 40; + if (0 <= shiftDist) { + return a ? packToF32UI(0, 0x95 - shiftDist, (uint32_t) a< +#include "internals.h" +#include "primitives.h" +#include "softfloat.h" + +float64 ui64_to_f64(uint64_t a, struct softfloat_status_t *status) +{ + if (! a) { + return 0; + } + if (a & UINT64_C(0x8000000000000000)) { + return softfloat_roundPackToF64(0, 0x43D, softfloat_shortShiftRightJam64(a, 1), status); + } else { + return softfloat_normRoundPackToF64(0, 0x43C, a, status); + } +} diff --git a/src/cpu/x86.c b/src/cpu/x86.c index 32b274f063..5eb16b98fb 100644 --- a/src/cpu/x86.c +++ b/src/cpu/x86.c @@ -83,7 +83,9 @@ int fpu_cycles = 0; int in_lock = 0; #ifdef ENABLE_X86_LOG +#if 0 void dumpregs(int); +#endif int x86_do_log = ENABLE_X86_LOG; int indump = 0; @@ -93,13 +95,14 @@ x86_log(const char *fmt, ...) { va_list ap; - if (x808x_do_log) { + if (x86_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } +#if 0 void dumpregs(int force) { @@ -144,6 +147,7 @@ dumpregs(int force) x87_dumpregs(); indump = 0; } +#endif #else # define x86_log(fmt, ...) #endif @@ -240,7 +244,6 @@ reset_common(int hard) if (!hard && reset_on_hlt) { hlt_reset_pending++; - pclog("hlt_reset_pending = %i\n", hlt_reset_pending); if (hlt_reset_pending == 2) hlt_reset_pending = 0; else @@ -274,7 +277,7 @@ reset_common(int hard) cr0 = 0; if (is386 && !is486 && (fpu_type == FPU_387)) cr0 |= 0x10; - cpu_cache_int_enabled = 0; + cpu_cache_int_enabled = 0; cpu_update_waitstates(); cr4 = 0; cpu_state.eflags = 0; @@ -322,6 +325,8 @@ reset_common(int hard) if (hard) codegen_reset(); #endif + cpu_flush_pending = 0; + cpu_old_paging = 0; if (!hard) flushmmucache(); x86_was_reset = 1; @@ -352,7 +357,8 @@ reset_common(int hard) /* If we have an AT or PS/2 keyboard controller, make sure the A20 state is correct. */ device_reset_all(DEVICE_KBC); - } + } else + device_reset_all(DEVICE_SOFTRESET); if (!is286) reset_808x(hard); diff --git a/src/cpu/x86.h b/src/cpu/x86.h index f52e430ac6..327af89640 100644 --- a/src/cpu/x86.h +++ b/src/cpu/x86.h @@ -59,6 +59,8 @@ extern int nmi_enable; extern int oddeven; extern int inttype; +extern int cpu_init; + extern uint32_t use32; extern uint32_t rmdat; extern uint32_t easeg; diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 6fb9b7a221..3dfb3f9176 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -90,10 +90,10 @@ extern const OpFn dynarec_ops_winchip2_0f[1024]; extern const OpFn dynarec_ops_pentium_0f[1024]; extern const OpFn dynarec_ops_pentiummmx_0f[1024]; -# if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +# ifdef USE_CYRIX_6X86 extern const OpFn dynarec_ops_c6x86_0f[1024]; extern const OpFn dynarec_ops_c6x86mx_0f[1024]; -# endif +# endif /* USE_CYRIX_6X86 */ extern const OpFn dynarec_ops_k6_0f[1024]; extern const OpFn dynarec_ops_k62_0f[1024]; @@ -232,10 +232,10 @@ extern const OpFn ops_winchip2_0f[1024]; extern const OpFn ops_pentium_0f[1024]; extern const OpFn ops_pentiummmx_0f[1024]; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 extern const OpFn ops_c6x86_0f[1024]; extern const OpFn ops_c6x86mx_0f[1024]; -#endif +#endif /* USE_CYRIX_6X86 */ extern const OpFn ops_k6_0f[1024]; extern const OpFn ops_k62_0f[1024]; @@ -434,9 +434,9 @@ extern const OpFn ops_2386_REPE[1024]; extern const OpFn ops_2386_REPNE[1024]; extern const OpFn ops_2386_3DNOW[256]; -#define C0 (1 << 8) -#define C1 (1 << 9) -#define C2 (1 << 10) -#define C3 (1 << 14) +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ #endif /*_X86_OPS_H*/ diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index 849e24e3df..9ea04b447d 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -4,6 +4,7 @@ static int opESCAPE_d8_a16(uint32_t fetchdat) { + //pclog("D8 A16: fetchdat=%02x.\n", (fetchdat >> 3) & 0x1f); return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int @@ -15,6 +16,7 @@ opESCAPE_d8_a32(uint32_t fetchdat) static int opESCAPE_d9_a16(uint32_t fetchdat) { + //pclog("D9 A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); } static int @@ -26,6 +28,7 @@ opESCAPE_d9_a32(uint32_t fetchdat) static int opESCAPE_da_a16(uint32_t fetchdat) { + //pclog("DA A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); } static int @@ -37,6 +40,7 @@ opESCAPE_da_a32(uint32_t fetchdat) static int opESCAPE_db_a16(uint32_t fetchdat) { + //pclog("DB A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); } static int @@ -48,6 +52,7 @@ opESCAPE_db_a32(uint32_t fetchdat) static int opESCAPE_dc_a16(uint32_t fetchdat) { + //pclog("DC A16: fetchdat=%02x.\n", (fetchdat >> 3) & 0x1f); return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); } static int @@ -59,6 +64,7 @@ opESCAPE_dc_a32(uint32_t fetchdat) static int opESCAPE_dd_a16(uint32_t fetchdat) { + //pclog("DD A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); } static int @@ -70,6 +76,7 @@ opESCAPE_dd_a32(uint32_t fetchdat) static int opESCAPE_de_a16(uint32_t fetchdat) { + //pclog("DE A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); } static int @@ -81,6 +88,7 @@ opESCAPE_de_a32(uint32_t fetchdat) static int opESCAPE_df_a16(uint32_t fetchdat) { + //pclog("DF A16: fetchdat=%02x.\n", fetchdat & 0xff); return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); } static int diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h index ab9d02d254..5e5dc3c7c3 100644 --- a/src/cpu/x86_ops_i686.h +++ b/src/cpu/x86_ops_i686.h @@ -100,8 +100,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) /* load i387 register file */ for (index = 0; index < 8; index++) { - reg.fraction = readmemq(easeg, cpu_state.eaaddr + (index * 16) + 32); - reg.exp = readmemw(easeg, cpu_state.eaaddr + (index * 16) + 40); + reg.signif = readmemq(easeg, cpu_state.eaaddr + (index * 16) + 32); + reg.signExp = readmemw(easeg, cpu_state.eaaddr + (index * 16) + 40); // update tag only if it is not empty FPU_save_regi_tag(reg, IS_TAG_EMPTY(index) ? X87_TAG_EMPTY : FPU_tagof(reg), index); @@ -159,8 +159,8 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits) for (index = 0; index < 8; index++) { const floatx80 fp = FPU_read_regi(index); - writememq(easeg, cpu_state.eaaddr + (index * 16) + 32, fp.fraction); - writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.exp); + writememq(easeg, cpu_state.eaaddr + (index * 16) + 32, fp.signif); + writememw(easeg, cpu_state.eaaddr + (index * 16) + 40, fp.signExp); } CLOCK_CYCLES((cr0 & 1) ? 56 : 67); diff --git a/src/cpu/x86_ops_mmx.c b/src/cpu/x86_ops_mmx.c index f26c903f94..2737ac8fa4 100644 --- a/src/cpu/x86_ops_mmx.c +++ b/src/cpu/x86_ops_mmx.c @@ -13,6 +13,7 @@ #include "cpu.h" #include <86box/timer.h> #include "x86.h" +#include "x87_sf.h" #include "x87.h" #include <86box/nmi.h> #include <86box/mem.h> @@ -33,7 +34,7 @@ uint16_t *MMEP[8]; static uint16_t MME[8]; -#define MMX_GETREGP(r) fpu_softfloat ? ((MMX_REG *) &fpu_state.st_space[r].fraction) : &(cpu_state.MM[r]) +#define MMX_GETREGP(r) fpu_softfloat ? ((MMX_REG *) &fpu_state.st_space[r].signif) : &(cpu_state.MM[r]) void mmx_init(void) { @@ -41,8 +42,8 @@ mmx_init(void) for (uint8_t i = 0; i < 8; i++) { if (fpu_softfloat) { - MMP[i] = (MMX_REG *) &fpu_state.st_space[i].fraction; - MMEP[i] = (uint16_t *) &fpu_state.st_space[i].exp; + MMP[i] = (MMX_REG *) &fpu_state.st_space[i].signif; + MMEP[i] = (uint16_t *) &fpu_state.st_space[i].signExp; } else { MMP[i] = &(cpu_state.MM[i]); MMEP[i] = &(MME[i]); diff --git a/src/cpu/x86_ops_mmx_mov.h b/src/cpu/x86_ops_mmx_mov.h index c72c8143d6..8855f8ccdd 100644 --- a/src/cpu/x86_ops_mmx_mov.h +++ b/src/cpu/x86_ops_mmx_mov.h @@ -110,7 +110,7 @@ opMOVD_mm_l_a32(uint32_t fetchdat) return 0; } -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) +#ifdef USE_CYRIX_6X86 /*Cyrix maps both MOVD and SMINT to the same opcode*/ static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) @@ -170,7 +170,7 @@ opMOVD_mm_l_a32_cx(uint32_t fetchdat) return 0; } -#endif +#endif /* USE_CYRIX_6X86 */ static int opMOVQ_q_mm_a16(uint32_t fetchdat) diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h index bcfed831b7..b4f0c498a6 100644 --- a/src/cpu/x86_ops_mov_ctrl.h +++ b/src/cpu/x86_ops_mov_ctrl.h @@ -9,6 +9,8 @@ opMOV_r_CRx_a16(uint32_t fetchdat) switch (cpu_reg) { case 0: cpu_state.regs[cpu_rm].l = cr0; + if (cpu_flush_pending) + cpu_state.regs[cpu_rm].l ^= 0x80000000; if (is486 || isibm486) cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ else { @@ -49,6 +51,8 @@ opMOV_r_CRx_a32(uint32_t fetchdat) switch (cpu_reg) { case 0: cpu_state.regs[cpu_rm].l = cr0; + if (cpu_flush_pending) + cpu_state.regs[cpu_rm].l ^= 0x80000000; if (is486 || isibm486) cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ else { @@ -180,8 +184,16 @@ opMOV_CRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); + else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { + if (is_p6 || cpu_use_dynarec) + flushmmucache(); + else { + flushmmucache_nopc(); + cpu_flush_pending = 1; + } + } /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; @@ -210,7 +222,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; @@ -237,8 +249,16 @@ opMOV_CRx_r_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); + else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { + if (is_p6 || cpu_use_dynarec) + flushmmucache(); + else { + flushmmucache_nopc(); + cpu_flush_pending = 1; + } + } /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; @@ -267,7 +287,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; diff --git a/src/cpu/x86_ops_mov_ctrl_2386.h b/src/cpu/x86_ops_mov_ctrl_2386.h index cae6c9957b..13e08a145e 100644 --- a/src/cpu/x86_ops_mov_ctrl_2386.h +++ b/src/cpu/x86_ops_mov_ctrl_2386.h @@ -9,6 +9,8 @@ opMOV_r_CRx_a16(uint32_t fetchdat) switch (cpu_reg) { case 0: cpu_state.regs[cpu_rm].l = cr0; + if (cpu_flush_pending) + cpu_state.regs[cpu_rm].l ^= 0x80000000; if (is486 || isibm486) cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ else { @@ -49,6 +51,8 @@ opMOV_r_CRx_a32(uint32_t fetchdat) switch (cpu_reg) { case 0: cpu_state.regs[cpu_rm].l = cr0; + if (cpu_flush_pending) + cpu_state.regs[cpu_rm].l ^= 0x80000000; if (is486 || isibm486) cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/ else { @@ -176,8 +180,12 @@ opMOV_CRx_r_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); + else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { + flushmmucache_nopc(); + cpu_flush_pending = 1; + } /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; @@ -206,7 +214,7 @@ opMOV_CRx_r_a16(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; @@ -233,8 +241,12 @@ opMOV_CRx_r_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); switch (cpu_reg) { case 0: - if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001) + if ((cpu_state.regs[cpu_rm].l ^ cr0) & (0x00000001 | WP_FLAG)) flushmmucache(); + else if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000000) { + flushmmucache_nopc(); + cpu_flush_pending = 1; + } /* Make sure CPL = 0 when switching from real mode to protected mode. */ if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01)) cpu_state.seg_cs.access &= 0x9f; @@ -263,7 +275,7 @@ opMOV_CRx_r_a32(uint32_t fetchdat) break; case 4: if (cpu_has_feature(CPU_FEATURE_CR4)) { - if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE)) + if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PSE | CR4_PAE | CR4_PGE)) flushmmucache(); cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask; break; diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h index e84847a7be..4f32b0e377 100644 --- a/src/cpu/x86_ops_pmode.h +++ b/src/cpu/x86_ops_pmode.h @@ -430,12 +430,21 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) case 0x20: /*SMSW*/ if (cpu_mod != 3) SEG_CHECK_WRITE(cpu_state.ea_seg); - if (is486 || isibm486) - seteaw(msw); - else if (is386) - seteaw(msw | /* 0xFF00 */ 0xFFE0); - else - seteaw(msw | 0xFFF0); + if (is386 && is32 && (cpu_mod == 3)) { + if (is486 || isibm486) + seteaw(cr0); + else if (is386 && !cpu_16bitbus) + seteaw(cr0 | /* 0x7FFFFF00 */ 0x7FFFFFE0); + else + seteaw(cr0 | 0x7FFFFFF0); + } else { + if (is486 || isibm486) + seteaw(msw); + else if (is386 && !cpu_16bitbus) + seteaw(msw | /* 0xFF00 */ 0xFFE0); + else + seteaw(msw | 0xFFF0); + } CLOCK_CYCLES(2); PREFETCH_RUN(2, 2, rmdat, 0, 0, (cpu_mod == 3) ? 0 : 1, 0, ea32); break; diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index d912a755bc..61c0edd9fd 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -48,12 +48,12 @@ #define seg_writememwl writememwl_2386 #define seg_writememll writememll_2386 #else -#define seg_readmembl readmembl_2386 -#define seg_readmemwl readmemwl_2386 -#define seg_readmemll readmemll_2386 -#define seg_writemembl writemembl_2386 -#define seg_writememwl writememwl_2386 -#define seg_writememll writememll_2386 +#define seg_readmembl readmembl +#define seg_readmemwl readmemwl +#define seg_readmemll readmemll +#define seg_writemembl writemembl +#define seg_writememwl writememwl +#define seg_writememll writememll #endif #define DPL ((segdat[2] >> 13) & 3) @@ -798,6 +798,27 @@ PUSHL(uint32_t v) } } +static void +PUSHL_SEL(uint32_t v) +{ + if (cpu_16bitbus) { + PUSHW(v >> 16); + PUSHW(v & 0xffff); + } else { + if (stack32) { + writememw(ss, ESP - 4, v); + if (cpu_state.abrt) + return; + ESP -= 4; + } else { + writememw(ss, ((SP - 4) & 0xffff), v); + if (cpu_state.abrt) + return; + SP -= 4; + } + } +} + static uint16_t POPW(void) { @@ -875,7 +896,7 @@ loadcscall(uint16_t seg) uint32_t oldsp; uint32_t newsp; uint32_t oldsp2; - uint16_t tempw; + uint32_t oldss_limit_high = cpu_state.seg_ss.limit_high; const x86seg *dt; if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { @@ -1092,7 +1113,7 @@ loadcscall(uint16_t seg) x86seg_log("Type %04X\n", type); if (type == 0x0c00) { - PUSHL(oldss); + PUSHL_SEL(oldss); PUSHL(oldsp2); if (cpu_state.abrt) { SS = oldss; @@ -1104,7 +1125,31 @@ loadcscall(uint16_t seg) } if (count) { while (count--) { - PUSHL(readmeml(oldssbase, oldsp + (count << 2))); + uint32_t temp_val; + switch (oldss_limit_high - oldsp - (count << 2)) { + default: + case 3: + /* We are at least an entire DWORD away from the limit, + read long. */ + PUSHL(readmeml(oldssbase, oldsp + (count << 2))); + break; + case 2: + /* We are 3 bytes away from the limit, + read word + byte. */ + temp_val = readmemw(oldssbase, oldsp + (count << 2)); + temp_val |= (readmemb(oldssbase, oldsp + + (count << 2) + 2) << 16); + PUSHL(temp_val); + break; + case 1: + /* We are a WORD away from the limit, read word. */ + PUSHL(readmemw(oldssbase, oldsp + (count << 2))); + break; + case 0: + /* We are a BYTE away from the limit, read byte. */ + PUSHL(readmemb(oldssbase, oldsp + (count << 2))); + break; + } if (cpu_state.abrt) { SS = oldss; ESP = oldsp2; @@ -1131,9 +1176,20 @@ loadcscall(uint16_t seg) x86seg_log("Write SP to %04X:%04X\n", SS, SP); if (count) { while (count--) { - tempw = readmemw(oldssbase, (oldsp & 0xffff) + (count << 1)); - x86seg_log("PUSH %04X\n", tempw); - PUSHW(tempw); + switch (oldss_limit_high - (oldsp & 0xffff) - (count << 1)) { + default: + case 1: + /* We are at least an entire WORD away from the limit, + read word. */ + PUSHW(readmemw(oldssbase, (oldsp & 0xffff) + + (count << 1))); + break; + case 0: + /* We are a BYTE away from the limit, read byte. */ + PUSHW(readmemb(oldssbase, (oldsp & 0xffff) + + (count << 1))); + break; + } if (cpu_state.abrt) { SS = oldss; ESP = oldsp2; @@ -1622,10 +1678,10 @@ pmodeint(int num, int soft) cpl_override = 1; if (type >= 0x0800) { if (cpu_state.eflags & VM_FLAG) { - PUSHL(GS); - PUSHL(FS); - PUSHL(DS); - PUSHL(ES); + PUSHL_SEL(GS); + PUSHL_SEL(FS); + PUSHL_SEL(DS); + PUSHL_SEL(ES); if (cpu_state.abrt) return; op_loadseg(0, &cpu_state.seg_ds); @@ -1633,10 +1689,10 @@ pmodeint(int num, int soft) op_loadseg(0, &cpu_state.seg_fs); op_loadseg(0, &cpu_state.seg_gs); } - PUSHL(oldss); + PUSHL_SEL(oldss); PUSHL(oldsp); PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); - PUSHL(CS); + PUSHL_SEL(CS); PUSHL(cpu_state.pc); if (cpu_state.abrt) return; @@ -1672,7 +1728,7 @@ pmodeint(int num, int soft) } if (type > 0x0800) { PUSHL(cpu_state.flags | (cpu_state.eflags << 16)); - PUSHL(CS); + PUSHL_SEL(CS); PUSHL(cpu_state.pc); if (cpu_state.abrt) return; diff --git a/src/cpu/x87.c b/src/cpu/x87.c index 1f7643453e..390c06dc27 100644 --- a/src/cpu/x87.c +++ b/src/cpu/x87.c @@ -14,31 +14,34 @@ #include "x86_flags.h" #include "x86_ops.h" #include "x86seg_common.h" +#include "x87_sf.h" #include "x87.h" #include "386_common.h" -#include "softfloat/softfloat-specialize.h" +#include "softfloat3e/config.h" +#include "softfloat3e/fpu_trans.h" +#include "softfloat3e/specialize.h" uint32_t x87_pc_off; uint32_t x87_op_off; uint16_t x87_pc_seg; uint16_t x87_op_seg; -#ifdef ENABLE_FPU_LOG -int fpu_do_log = ENABLE_FPU_LOG; +#ifdef ENABLE_FPU_X87_LOG +int fpu_x87_do_log = ENABLE_FPU_X87_LOG; void -fpu_log(const char *fmt, ...) +fpu_x87_log(const char *fmt, ...) { va_list ap; - if (fpu_do_log) { + if (fpu_x87_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -# define fpu_log(fmt, ...) +# define fpu_x87_log(fmt, ...) #endif #ifdef USE_NEW_DYNAREC @@ -106,24 +109,24 @@ x87_settag(uint16_t new_tag) } #endif -static floatx80 -FPU_handle_NaN32_Func(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, struct float_status_t *status) +static extFloat80_t +FPU_handle_NaN32_Func(extFloat80_t a, int aIsNaN, float32 b32, int bIsNaN, struct softfloat_status_t *status) { - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsSignalingNaN = float32_is_signaling_nan(b32); + int aIsSignalingNaN = extF80_isSignalingNaN(a); + int bIsSignalingNaN = f32_isSignalingNaN(b32); if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); // propagate QNaN to SNaN - a = propagateFloatx80NaNOne(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, 0, 0, status); if (aIsNaN & !bIsNaN) return a; // float32 is NaN so conversion will propagate SNaN to QNaN and raise // appropriate exception flags - floatx80 b = float32_to_floatx80(b32, status); + extFloat80_t b = f32_to_extF80(b32, status); if (aIsSignalingNaN) { if (bIsSignalingNaN) @@ -133,29 +136,33 @@ FPU_handle_NaN32_Func(floatx80 a, int aIsNaN, float32 b32, int bIsNaN, struct fl if (bIsSignalingNaN) return a; returnLargerSignificand: - if (a.fraction < b.fraction) + if (a.signif < b.signif) return b; - if (b.fraction < a.fraction) + if (b.signif < a.signif) return a; - return (a.exp < b.exp) ? a : b; + return (a.signExp < b.signExp) ? a : b; } else { return b; } } int -FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *status) +FPU_handle_NaN32(extFloat80_t a, float32 b, extFloat80_t *r, struct softfloat_status_t *status) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return 1; } - int aIsNaN = floatx80_is_nan(a); - int bIsNaN = float32_is_nan(b); + int aIsNaN = extF80_isNaN(a); + int bIsNaN = f32_isNaN(b); if (aIsNaN | bIsNaN) { *r = FPU_handle_NaN32_Func(a, aIsNaN, b, bIsNaN, status); return 1; @@ -163,24 +170,24 @@ FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *stat return 0; } -static floatx80 -FPU_handle_NaN64_Func(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, struct float_status_t *status) +static extFloat80_t +FPU_handle_NaN64_Func(extFloat80_t a, int aIsNaN, float64 b64, int bIsNaN, struct softfloat_status_t *status) { - int aIsSignalingNaN = floatx80_is_signaling_nan(a); - int bIsSignalingNaN = float64_is_signaling_nan(b64); + int aIsSignalingNaN = extF80_isSignalingNaN(a); + int bIsSignalingNaN = f64_isSignalingNaN(b64); if (aIsSignalingNaN | bIsSignalingNaN) - float_raise(status, float_flag_invalid); + softfloat_raiseFlags(status, softfloat_flag_invalid); // propagate QNaN to SNaN - a = propagateFloatx80NaNOne(a, status); + a = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, 0, 0, status); if (aIsNaN & !bIsNaN) return a; // float64 is NaN so conversion will propagate SNaN to QNaN and raise // appropriate exception flags - floatx80 b = float64_to_floatx80(b64, status); + extFloat80_t b = f64_to_extF80(b64, status); if (aIsSignalingNaN) { if (bIsSignalingNaN) @@ -190,29 +197,33 @@ FPU_handle_NaN64_Func(floatx80 a, int aIsNaN, float64 b64, int bIsNaN, struct fl if (bIsSignalingNaN) return a; returnLargerSignificand: - if (a.fraction < b.fraction) + if (a.signif < b.signif) return b; - if (b.fraction < a.fraction) + if (b.signif < a.signif) return a; - return (a.exp < b.exp) ? a : b; + return (a.signExp < b.signExp) ? a : b; } else { return b; } } int -FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *status) +FPU_handle_NaN64(extFloat80_t a, float64 b, extFloat80_t *r, struct softfloat_status_t *status) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - - if (floatx80_is_unsupported(a)) { - float_raise(status, float_flag_invalid); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const extFloat80_t floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + + if (extF80_isUnsupported(a)) { + softfloat_raiseFlags(status, softfloat_flag_invalid); *r = floatx80_default_nan; return 1; } - int aIsNaN = floatx80_is_nan(a); - int bIsNaN = float64_is_nan(b); + int aIsNaN = extF80_isNaN(a); + int bIsNaN = f64_isNaN(b); if (aIsNaN | bIsNaN) { *r = FPU_handle_NaN64_Func(a, aIsNaN, b, bIsNaN, status); return 1; @@ -220,37 +231,36 @@ FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *stat return 0; } -struct float_status_t +struct softfloat_status_t i387cw_to_softfloat_status_word(uint16_t control_word) { - struct float_status_t status; + struct softfloat_status_t status; int precision = control_word & FPU_CW_PC; switch (precision) { case FPU_PR_32_BITS: - status.float_rounding_precision = 32; + status.extF80_roundingPrecision = 32; break; case FPU_PR_64_BITS: - status.float_rounding_precision = 64; + status.extF80_roundingPrecision = 64; break; case FPU_PR_80_BITS: - status.float_rounding_precision = 80; + status.extF80_roundingPrecision = 80; break; default: /* With the precision control bits set to 01 "(reserved)", a real CPU behaves as if the precision control bits were set to 11 "80 bits" */ - status.float_rounding_precision = 80; + status.extF80_roundingPrecision = 80; break; } - status.float_exception_flags = 0; // clear exceptions before execution - status.float_nan_handling_mode = float_first_operand_nan; - status.float_rounding_mode = (control_word & FPU_CW_RC) >> 10; - status.flush_underflow_to_zero = 0; - status.float_suppress_exception = 0; - status.float_exception_masks = control_word & FPU_CW_Exceptions_Mask; - status.denormals_are_zeros = 0; + status.softfloat_exceptionFlags = 0; // clear exceptions before execution + status.softfloat_roundingMode = (control_word & FPU_CW_RC) >> 10; + status.softfloat_flush_underflow_to_zero = 0; + status.softfloat_suppressException = 0; + status.softfloat_exceptionMasks = control_word & FPU_CW_Exceptions_Mask; + status.softfloat_denormals_are_zeros = 0; return status; } @@ -258,17 +268,20 @@ int FPU_status_word_flags_fpu_compare(int float_relation) { switch (float_relation) { - case float_relation_unordered: - return (C0 | C2 | C3); + case softfloat_relation_unordered: + return (FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); - case float_relation_greater: + case softfloat_relation_greater: return 0; - case float_relation_less: - return C0; + case softfloat_relation_less: + return FPU_SW_C0; - case float_relation_equal: - return C3; + case softfloat_relation_equal: + return FPU_SW_C3; + + default: + break; } return (-1); // should never get here @@ -278,18 +291,18 @@ void FPU_write_eflags_fpu_compare(int float_relation) { switch (float_relation) { - case float_relation_unordered: + case softfloat_relation_unordered: cpu_state.flags |= (Z_FLAG | P_FLAG | C_FLAG); break; - case float_relation_greater: + case softfloat_relation_greater: break; - case float_relation_less: + case softfloat_relation_less: cpu_state.flags |= C_FLAG; break; - case float_relation_equal: + case softfloat_relation_equal: cpu_state.flags |= Z_FLAG; break; @@ -324,10 +337,10 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) // FPU_EX_Invalid cannot come with any other exception but x87 stack fault fpu_state.swd |= exceptions; if (exceptions & FPU_SW_Stack_Fault) { - if (!(exceptions & C1)) { + if (!(exceptions & FPU_SW_C1)) { /* This bit distinguishes over- from underflow for a stack fault, and roundup from round-down for precision loss. */ - fpu_state.swd &= ~C1; + fpu_state.swd &= ~FPU_SW_C1; } } return unmasked; @@ -359,10 +372,10 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) fpu_state.swd |= exceptions; if (exceptions & FPU_EX_Precision) { - if (!(exceptions & C1)) { + if (!(exceptions & FPU_SW_C1)) { /* This bit distinguishes over- from underflow for a stack fault, and roundup from round-down for precision loss. */ - fpu_state.swd &= ~C1; + fpu_state.swd &= ~FPU_SW_C1; } } @@ -380,7 +393,7 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) if (!store) unmasked &= ~(FPU_EX_Underflow | FPU_EX_Overflow); else { - fpu_state.swd &= ~C1; + fpu_state.swd &= ~FPU_SW_C1; if (!(status & FPU_EX_Precision)) fpu_state.swd &= ~FPU_EX_Precision; } @@ -391,7 +404,11 @@ FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store) void FPU_stack_overflow(uint32_t fetchdat) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); /* The masked response */ if (is_IA_masked()) { @@ -404,7 +421,11 @@ FPU_stack_overflow(uint32_t fetchdat) void FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +/*---------------------------------------------------------------------------- +| The pattern for a default generated extended double-precision NaN. +*----------------------------------------------------------------------------*/ + const floatx80 floatx80_default_nan = + packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); /* The masked response */ if (is_IA_masked()) { @@ -420,11 +441,11 @@ FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack) * rather than a kernel (ported by Kevin Lawton) * ------------------------------------------------------------ */ int -FPU_tagof(const floatx80 reg) +FPU_tagof(const extFloat80_t reg) { - int32_t exp = floatx80_exp(reg); + int32_t exp = extF80_exp(reg); if (exp == 0) { - if (!floatx80_fraction(reg)) + if (!extF80_fraction(reg)) return X87_TAG_ZERO; /* The number is a de-normal or pseudodenormal. */ @@ -436,7 +457,7 @@ FPU_tagof(const floatx80 reg) return X87_TAG_INVALID; } - if (!(reg.fraction & BX_CONST64(0x8000000000000000))) { + if (!(reg.signif & BX_CONST64(0x8000000000000000))) { /* Unsupported data type. */ /* Valid numbers have the ms bit set to 1. */ return X87_TAG_INVALID; @@ -516,28 +537,26 @@ unpack_FPU_TW(uint16_t tag_byte) */ for (int index = 7; index >= 0; index--, twd <<= 2, tag_byte <<= 1) { - if (tag_byte & 0x80) { - const floatx80 *fpu_reg = &fpu_state.st_space[index & 7]; - twd |= FPU_tagof(*fpu_reg); - } else { + if (tag_byte & 0x80) + twd |= FPU_tagof(fpu_state.st_space[index & 7]); + else twd |= X87_TAG_EMPTY; - } } return (twd >> 2); } -#ifdef ENABLE_808X_LOG +#ifdef ENABLE_FPU_X87_LOG void x87_dumpregs(void) { if (cpu_state.ismmx) { - fpu_log("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); - fpu_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); + fpu_x87_log("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q); + fpu_x87_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q); } else { - fpu_log("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n", cpu_state.ST[cpu_state.TOP], cpu_state.ST[(cpu_state.TOP + 1) & 7], cpu_state.ST[(cpu_state.TOP + 2) & 7], cpu_state.ST[(cpu_state.TOP + 3) & 7]); - fpu_log("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n", cpu_state.ST[(cpu_state.TOP + 4) & 7], cpu_state.ST[(cpu_state.TOP + 5) & 7], cpu_state.ST[(cpu_state.TOP + 6) & 7], cpu_state.ST[(cpu_state.TOP + 7) & 7]); + fpu_x87_log("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n", cpu_state.ST[cpu_state.TOP], cpu_state.ST[(cpu_state.TOP + 1) & 7], cpu_state.ST[(cpu_state.TOP + 2) & 7], cpu_state.ST[(cpu_state.TOP + 3) & 7]); + fpu_x87_log("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n", cpu_state.ST[(cpu_state.TOP + 4) & 7], cpu_state.ST[(cpu_state.TOP + 5) & 7], cpu_state.ST[(cpu_state.TOP + 6) & 7], cpu_state.ST[(cpu_state.TOP + 7) & 7]); } - fpu_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); + fpu_x87_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag()); } #endif diff --git a/src/cpu/x87.h b/src/cpu/x87.h index f4e24f1ca6..060f2fe276 100644 --- a/src/cpu/x87.h +++ b/src/cpu/x87.h @@ -60,89 +60,80 @@ void x87_settag(uint16_t new_tag); void codegen_set_rounding_mode(int mode); /* Status Word */ -#define FPU_SW_Backward (0x8000) /* backward compatibility */ -#define FPU_SW_C3 (0x4000) /* condition bit 3 */ -#define FPU_SW_Top (0x3800) /* top of stack */ -#define FPU_SW_C2 (0x0400) /* condition bit 2 */ -#define FPU_SW_C1 (0x0200) /* condition bit 1 */ -#define FPU_SW_C0 (0x0100) /* condition bit 0 */ -#define FPU_SW_Summary (0x0080) /* exception summary */ -#define FPU_SW_Stack_Fault (0x0040) /* stack fault */ -#define FPU_SW_Precision (0x0020) /* loss of precision */ -#define FPU_SW_Underflow (0x0010) /* underflow */ -#define FPU_SW_Overflow (0x0008) /* overflow */ -#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ -#define FPU_SW_Denormal_Op (0x0002) /* denormalized operand */ -#define FPU_SW_Invalid (0x0001) /* invalid operation */ - -#define C0 (1 << 8) -#define C1 (1 << 9) -#define C2 (1 << 10) -#define C3 (1 << 14) - -#define FPU_SW_CC (C0 | C1 | C2 | C3) - -#define FPU_SW_Exceptions_Mask (0x027f) /* status word exceptions bit mask */ +#define FPU_SW_Backward (0x8000) /* backward compatibility */ +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_Top (0x3800) /* top of stack */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ +#define FPU_SW_Summary (0x0080) /* exception summary */ +#define FPU_SW_Stack_Fault (0x0040) /* stack fault */ +#define FPU_SW_Precision (0x0020) /* loss of precision */ +#define FPU_SW_Underflow (0x0010) /* underflow */ +#define FPU_SW_Overflow (0x0008) /* overflow */ +#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ +#define FPU_SW_Denormal_Op (0x0002) /* denormalized operand */ +#define FPU_SW_Invalid (0x0001) /* invalid operation */ + +#define FPU_SW_CC (FPU_SW_C0|FPU_SW_C1|FPU_SW_C2|FPU_SW_C3) + +#define FPU_SW_Exceptions_Mask (0x027f) /* status word exceptions bit mask */ /* Exception flags: */ -#define FPU_EX_Precision (0x0020) /* loss of precision */ -#define FPU_EX_Underflow (0x0010) /* underflow */ -#define FPU_EX_Overflow (0x0008) /* overflow */ -#define FPU_EX_Zero_Div (0x0004) /* divide by zero */ -#define FPU_EX_Denormal (0x0002) /* denormalized operand */ -#define FPU_EX_Invalid (0x0001) /* invalid operation */ +#define FPU_EX_Precision (0x0020) /* loss of precision */ +#define FPU_EX_Underflow (0x0010) /* underflow */ +#define FPU_EX_Overflow (0x0008) /* overflow */ +#define FPU_EX_Zero_Div (0x0004) /* divide by zero */ +#define FPU_EX_Denormal (0x0002) /* denormalized operand */ +#define FPU_EX_Invalid (0x0001) /* invalid operation */ /* Special exceptions: */ -#define FPU_EX_Stack_Overflow (0x0041 | C1) /* stack overflow */ -#define FPU_EX_Stack_Underflow (0x0041) /* stack underflow */ +#define FPU_EX_Stack_Overflow (0x0041|FPU_SW_C1) /* stack overflow */ +#define FPU_EX_Stack_Underflow (0x0041) /* stack underflow */ /* precision control */ -#define FPU_EX_Precision_Lost_Up (EX_Precision | C1) -#define FPU_EX_Precision_Lost_Dn (EX_Precision) +#define FPU_EX_Precision_Lost_Up (EX_Precision | SW_C1) +#define FPU_EX_Precision_Lost_Dn (EX_Precision) -#define setcc(cc) \ - fpu_state.swd = (fpu_state.swd & ~(FPU_SW_CC)) | ((cc) &FPU_SW_CC) +#define setcc(cc) \ + fpu_state.swd = (fpu_state.swd & ~(FPU_SW_CC)) | ((cc) & FPU_SW_CC) -#define clear_C1() \ - { \ - fpu_state.swd &= ~C1; \ - } -#define clear_C2() \ - { \ - fpu_state.swd &= ~C2; \ - } +#define clear_C1() { fpu_state.swd &= ~FPU_SW_C1; } +#define clear_C2() { fpu_state.swd &= ~FPU_SW_C2; } /* ************ */ /* Control Word */ /* ************ */ -#define FPU_CW_Inf (0x1000) /* infinity control, legacy */ +#define FPU_CW_Reserved_Bits (0xe0c0) /* reserved bits */ + +#define FPU_CW_Inf (0x1000) /* infinity control, legacy */ -#define FPU_CW_RC (0x0C00) /* rounding control */ -#define FPU_CW_PC (0x0300) /* precision control */ +#define FPU_CW_RC (0x0C00) /* rounding control */ +#define FPU_CW_PC (0x0300) /* precision control */ -#define FPU_RC_RND (0x0000) /* rounding control */ -#define FPU_RC_DOWN (0x0400) -#define FPU_RC_UP (0x0800) -#define FPU_RC_CHOP (0x0C00) +#define FPU_RC_RND (0x0000) /* rounding control */ +#define FPU_RC_DOWN (0x0400) +#define FPU_RC_UP (0x0800) +#define FPU_RC_CHOP (0x0C00) -#define FPU_CW_Precision (0x0020) /* loss of precision mask */ -#define FPU_CW_Underflow (0x0010) /* underflow mask */ -#define FPU_CW_Overflow (0x0008) /* overflow mask */ -#define FPU_CW_Zero_Div (0x0004) /* divide by zero mask */ -#define FPU_CW_Denormal (0x0002) /* denormalized operand mask */ -#define FPU_CW_Invalid (0x0001) /* invalid operation mask */ +#define FPU_CW_Precision (0x0020) /* loss of precision mask */ +#define FPU_CW_Underflow (0x0010) /* underflow mask */ +#define FPU_CW_Overflow (0x0008) /* overflow mask */ +#define FPU_CW_Zero_Div (0x0004) /* divide by zero mask */ +#define FPU_CW_Denormal (0x0002) /* denormalized operand mask */ +#define FPU_CW_Invalid (0x0001) /* invalid operation mask */ -#define FPU_CW_Exceptions_Mask (0x003f) /* all masks */ +#define FPU_CW_Exceptions_Mask (0x003f) /* all masks */ /* Precision control bits affect only the following: ADD, SUB(R), MUL, DIV(R), and SQRT */ -#define FPU_PR_32_BITS (0x000) -#define FPU_PR_RESERVED_BITS (0x100) -#define FPU_PR_64_BITS (0x200) -#define FPU_PR_80_BITS (0x300) +#define FPU_PR_32_BITS (0x000) +#define FPU_PR_RESERVED_BITS (0x100) +#define FPU_PR_64_BITS (0x200) +#define FPU_PR_80_BITS (0x300) -#include "softfloat/softfloatx80.h" +#include "softfloat3e/softfloat.h" static __inline int is_IA_masked(void) @@ -150,15 +141,15 @@ is_IA_masked(void) return (fpu_state.cwd & FPU_CW_Invalid); } -struct float_status_t i387cw_to_softfloat_status_word(uint16_t control_word); +struct softfloat_status_t i387cw_to_softfloat_status_word(uint16_t control_word); uint16_t FPU_exception(uint32_t fetchdat, uint16_t exceptions, int store); int FPU_status_word_flags_fpu_compare(int float_relation); void FPU_write_eflags_fpu_compare(int float_relation); void FPU_stack_overflow(uint32_t fetchdat); void FPU_stack_underflow(uint32_t fetchdat, int stnr, int pop_stack); -int FPU_handle_NaN32(floatx80 a, float32 b, floatx80 *r, struct float_status_t *status); -int FPU_handle_NaN64(floatx80 a, float64 b, floatx80 *r, struct float_status_t *status); -int FPU_tagof(const floatx80 reg); +int FPU_handle_NaN32(extFloat80_t a, float32 b, extFloat80_t *r, struct softfloat_status_t *status); +int FPU_handle_NaN64(extFloat80_t a, float64 b, extFloat80_t *r, struct softfloat_status_t *status); +int FPU_tagof(const extFloat80_t reg); uint8_t pack_FPU_TW(uint16_t twd); uint16_t unpack_FPU_TW(uint16_t tag_byte); @@ -207,11 +198,11 @@ FPU_push(void) static __inline void FPU_pop(void) { - fpu_state.tag |= 3 << (fpu_state.tos * 2); + fpu_state.tag |= (3 << (fpu_state.tos * 2)); fpu_state.tos = (fpu_state.tos + 1) & 7; } -static __inline floatx80 +static __inline extFloat80_t FPU_read_regi(int stnr) { return fpu_state.st_space[(stnr + fpu_state.tos) & 7]; @@ -221,14 +212,14 @@ FPU_read_regi(int stnr) // instructions like FNSAVE, and they update tag word to its // real value anyway static __inline void -FPU_save_regi(floatx80 reg, int stnr) +FPU_save_regi(extFloat80_t reg, int stnr) { fpu_state.st_space[(stnr + fpu_state.tos) & 7] = reg; FPU_settagi_valid(stnr); } static __inline void -FPU_save_regi_tag(floatx80 reg, int tag, int stnr) +FPU_save_regi_tag(extFloat80_t reg, int tag, int stnr) { fpu_state.st_space[(stnr + fpu_state.tos) & 7] = reg; FPU_settagi(tag, stnr); diff --git a/src/cpu/x87_ops.h b/src/cpu/x87_ops.h index aef9289e75..6be9d7648f 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu/x87_ops.h @@ -40,17 +40,17 @@ static int rounding_modes[4] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARD #define ST(x) cpu_state.ST[((cpu_state.TOP + (x)) & 7)] -#define C0 (1 << 8) -#define C1 (1 << 9) -#define C2 (1 << 10) -#define C3 (1 << 14) +#define FPU_SW_C3 (0x4000) /* condition bit 3 */ +#define FPU_SW_C2 (0x0400) /* condition bit 2 */ +#define FPU_SW_C1 (0x0200) /* condition bit 1 */ +#define FPU_SW_C0 (0x0100) /* condition bit 0 */ #define X87_TAG_VALID 0 #define X87_TAG_ZERO 1 #define X87_TAG_INVALID 2 #define X87_TAG_EMPTY 3 -#define STATUS_ZERODIVIDE 4 +#define FPU_SW_Zero_Div (0x0004) /* divide by zero */ typedef union { double d; @@ -76,8 +76,8 @@ typedef union { # define x87_div(dst, src1, src2) \ do { \ if (((double) src2) == 0.0) { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + cpu_state.npxs |= FPU_SW_Zero_Div; \ + if (cpu_state.npxc & FPU_SW_Zero_Div) \ dst = src1 / (double) src2; \ else { \ fpu_log("FPU : divide by zero\n"); \ @@ -94,8 +94,8 @@ typedef union { # define x87_div(dst, src1, src2) \ do { \ if (((double) src2) == 0.0) { \ - cpu_state.npxs |= STATUS_ZERODIVIDE; \ - if (cpu_state.npxc & STATUS_ZERODIVIDE) \ + cpu_state.npxs |= FPU_SW_Zero_Div; \ + if (cpu_state.npxc & FPU_SW_Zero_Div) \ dst = src1 / (double) src2; \ else { \ fpu_log("FPU : divide by zero\n"); \ @@ -107,12 +107,6 @@ typedef union { } while (0) #endif -static __inline void -x87_checkexceptions(void) -{ - // -} - static __inline void x87_push(double i) { @@ -366,7 +360,7 @@ x87_compare(double a, double b) /* Hack to make CHKCOP happy. */ if (!memcmp(&ea, &ia, 8) && !memcmp(&eb, &ib, 8)) - return C3; + return FPU_SW_C3; if ((fpu_type < FPU_287XL) && !(cpu_state.npxc & 0x1000) && ((a == INFINITY) || (a == -INFINITY)) && ((b == INFINITY) || (b == -INFINITY))) eb = ea; @@ -399,7 +393,7 @@ x87_compare(double a, double b) } # endif - return result & (C0 | C2 | C3); + return result & (FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ @@ -410,9 +404,9 @@ x87_compare(double a, double b) eb = ea; if (ea == eb) - result |= C3; + result |= FPU_SW_C3; else if (ea < eb) - result |= C0; + result |= FPU_SW_C0; return result; #endif @@ -452,16 +446,16 @@ x87_ucompare(double a, double b) } # endif - return result & (C0 | C2 | C3); + return result & (FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ uint32_t result = 0; if (a == b) - result |= C3; + result |= FPU_SW_C3; else if (a < b) - result |= C0; + result |= FPU_SW_C0; return result; #endif @@ -503,7 +497,8 @@ typedef union { # define FP_TAG_VALID_N cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64 #endif -#include "softfloat/softfloat-specialize.h" +#include "softfloat3e/softfloat-specialize.h" +#include "softfloat3e/fpu_trans.h" #include "x87_ops_sf_arith.h" #include "x87_ops_sf_compare.h" @@ -1093,10 +1088,10 @@ const OpFn OP_TABLE(fpu_8087_df)[256] = { const OpFn OP_TABLE(sf_fpu_d8_a16)[32] = { // clang-format off - sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, - sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, - sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, - sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, + /*0x00*/ sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + /*0x08*/ sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + /*0x10*/ sf_FADDs_a16, sf_FMULs_a16, sf_FCOMs_a16, sf_FCOMPs_a16, sf_FSUBs_a16, sf_FSUBRs_a16, sf_FDIVs_a16, sf_FDIVRs_a16, + /*0x18*/ sf_FADD_st0_stj, sf_FMUL_st0_stj, sf_FCOM_sti, sf_FCOMP_sti, sf_FSUB_st0_stj, sf_FSUBR_st0_stj, sf_FDIV_st0_stj, sf_FDIVR_st0_stj, // clang-format on }; @@ -1191,41 +1186,41 @@ const OpFn OP_TABLE(sf_fpu_287_d9_a32)[256] = { const OpFn OP_TABLE(sf_fpu_d9_a16)[256] = { // clang-format off - sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, - sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, - sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, - sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, - sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, - sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, - - sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, - sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, - sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, - sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, - sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, - sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, - - sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, - sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, - sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, - sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, - sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, - sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, - - sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, - sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, - sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ - sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, - sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, - sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, - sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, + /*0x00*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x18*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x20*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x28*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x30*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x38*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0x40*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x58*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0x60*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0x68*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0x70*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0x78*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0x80*/ sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, sf_FLDs_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, sf_FSTs_a16, + /*0x98*/ sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, sf_FSTPs_a16, + /*0xa0*/ sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, sf_FLDENV_a16, + /*0xa8*/ sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, sf_FLDCW_a16, + /*0xb0*/ sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, sf_FNSTENV_a16, + /*0xb8*/ sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, sf_FNSTCW_a16, + + /*0xc0*/ sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, sf_FLD_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, /*Invalid*/ + /*0xe0*/ sf_FCHS, sf_FABS, ILLEGAL_a16, ILLEGAL_a16, sf_FTST, sf_FXAM, ILLEGAL_a16, ILLEGAL_a16, + /*0xe8*/ sf_FLD1, sf_FLDL2T, sf_FLDL2E, sf_FLDPI, sf_FLDEG2, sf_FLDLN2, sf_FLDZ, ILLEGAL_a16, + /*0xf0*/ sf_F2XM1, sf_FYL2X, sf_FPTAN, sf_FPATAN, sf_FXTRACT, sf_FPREM1, sf_FDECSTP, sf_FINCSTP, + /*0xf8*/ sf_FPREM, sf_FYL2XP1, sf_FSQRT, sf_FSINCOS, sf_FRNDINT, sf_FSCALE, sf_FSIN, sf_FCOS, // clang-format on }; @@ -1593,41 +1588,41 @@ const OpFn OP_TABLE(sf_fpu_287_db_a32)[256] = { const OpFn OP_TABLE(sf_fpu_db_a16)[256] = { // clang-format off - sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, - sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, - - sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, - sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, - - sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, - sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, - - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x00*/ sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + /*0x18*/ sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + /*0x20*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x28*/ sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + /*0x30*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x38*/ sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + /*0x40*/ sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + /*0x58*/ sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + /*0x60*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x68*/ sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + /*0x70*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x78*/ sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + /*0x80*/ sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, sf_FISTil_a16, + /*0x98*/ sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, sf_FISTPil_a16, + /*0xa0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xa8*/ sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, sf_FLDe_a16, + /*0xb0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xb8*/ sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, sf_FSTPe_a16, + + /*0xc0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xc8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xd8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xe0*/ sf_FNOP, sf_FNOP, sf_FNCLEX, sf_FNINIT, sf_FNOP, sf_FNOP, ILLEGAL_a16, ILLEGAL_a16, + /*0xe8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, // clang-format on }; @@ -1870,41 +1865,41 @@ const OpFn OP_TABLE(sf_fpu_287_dd_a32)[256] = { const OpFn OP_TABLE(sf_fpu_dd_a16)[256] = { // clang-format off - sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, - sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, - sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, - sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, - - sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, - sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, - sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, - sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, - - sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, - sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, - sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, - sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, - - sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, - sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, - sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, - sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, - sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x00*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x18*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x20*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x28*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x30*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x38*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0x40*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x58*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0x60*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0x68*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x70*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0x78*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0x80*/ sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, sf_FLDd_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, sf_FSTd_a16, + /*0x98*/ sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, sf_FSTPd_a16, + /*0xa0*/ sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, sf_FRSTOR_a16, + /*0xa8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xb0*/ sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, sf_FNSAVE_a16, + /*0xb8*/ sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, sf_FNSTSW_a16, + + /*0xc0*/ sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, sf_FFREE_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, sf_FST_sti, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xe0*/ sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, sf_FUCOM_sti, + /*0xe8*/ sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, sf_FUCOMP_sti, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, // clang-format on }; @@ -2030,41 +2025,41 @@ const OpFn OP_TABLE(sf_fpu_287_de_a32)[256] = { const OpFn OP_TABLE(sf_fpu_de_a16)[256] = { // clang-format off - sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, - sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, - sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, - sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, - sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, - sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, - sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, - sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, - - sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, - sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, - sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, - sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, - sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, - sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, - sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, - sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, - - sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, - sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, - sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, - sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, - sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, - sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, - sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, - sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, - - sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, - sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, - sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, - ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, - sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, - sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, - sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, + /*0x00*/ sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + /*0x08*/ sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + /*0x10*/ sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + /*0x18*/ sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + /*0x20*/ sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + /*0x28*/ sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + /*0x30*/ sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + /*0x38*/ sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + /*0x40*/ sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + /*0x48*/ sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + /*0x50*/ sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + /*0x58*/ sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + /*0x60*/ sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + /*0x68*/ sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + /*0x70*/ sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + /*0x78*/ sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + /*0x80*/ sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, sf_FADDiw_a16, + /*0x88*/ sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, sf_FMULiw_a16, + /*0x90*/ sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, sf_FCOMiw_a16, + /*0x98*/ sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, sf_FCOMPiw_a16, + /*0xa0*/ sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, sf_FSUBiw_a16, + /*0xa8*/ sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, sf_FSUBRiw_a16, + /*0xb0*/ sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, sf_FDIViw_a16, + /*0xb8*/ sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, sf_FDIVRiw_a16, + + /*0xc0*/ sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, sf_FADDP_sti_st0, + /*0xc8*/ sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, sf_FMULP_sti_st0, + /*0xd0*/ sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, sf_FCOMP_sti, + /*0xd8*/ ILLEGAL_a16, sf_FCOMPP, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xe0*/ sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, sf_FSUBRP_sti_st0, + /*0xe8*/ sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, sf_FSUBP_sti_st0, + /*0xf0*/ sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, sf_FDIVRP_sti_st0, + /*0xf8*/ sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, sf_FDIVP_sti_st0, // clang-format on }; @@ -2190,41 +2185,41 @@ const OpFn OP_TABLE(sf_fpu_287_df_a32)[256] = { const OpFn OP_TABLE(sf_fpu_df_a16)[256] = { // clang-format off - sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, - sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, - sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, - sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, - sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, - sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, - - sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, - sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, - sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, - sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, - sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, - sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, - - sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, - sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, - sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, - sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, - sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, - sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, - - sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, - sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, - sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, - sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, - ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x00*/ sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + /*0x08*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x10*/ sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + /*0x18*/ sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + /*0x20*/ sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + /*0x28*/ sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + /*0x30*/ sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + /*0x38*/ sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + /*0x40*/ sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + /*0x48*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x50*/ sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + /*0x58*/ sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + /*0x60*/ sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + /*0x68*/ sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + /*0x70*/ sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + /*0x78*/ sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + /*0x80*/ sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, + /*0x88*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0x90*/ sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, sf_FISTiw_a16, + /*0x98*/ sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, sf_FISTPiw_a16, + /*0xa0*/ sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, sf_FBLD_PACKED_BCD_a16, + /*0xa8*/ sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, sf_FILDiq_a16, + /*0xb0*/ sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, sf_FBSTP_PACKED_BCD_a16, + /*0xb8*/ sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, sf_FISTPiq_a16, + + /*0xc0*/ sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, sf_FFREEP_sti, + /*0xc8*/ sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, sf_FXCH_sti, + /*0xd0*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xd8*/ sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, sf_FSTP_sti, + /*0xe0*/ sf_FNSTSW_AX, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xe8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf0*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, + /*0xf8*/ ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, // clang-format on }; diff --git a/src/cpu/x87_ops_arith.h b/src/cpu/x87_ops_arith.h index 808a150517..31c26231b3 100644 --- a/src/cpu/x87_ops_arith.h +++ b/src/cpu/x87_ops_arith.h @@ -27,7 +27,7 @@ load_var = get(); \ if (cpu_state.abrt) \ return 1; \ - cpu_state.npxs &= ~(C0 | C2 | C3); \ + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom##cycle_postfix) : ((x87_concurrency.fcom##cycle_postfix) * cpu_multi)); \ @@ -42,7 +42,7 @@ load_var = get(); \ if (cpu_state.abrt) \ return 1; \ - cpu_state.npxs &= ~(C0 | C2 | C3); \ + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ cpu_state.npxs |= x87_compare(ST(0), (double) use_var); \ x87_pop(); \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ @@ -128,24 +128,24 @@ // clang-format off opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32) #ifndef FPU_8087 - opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) +opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32) #endif opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64) #ifndef FPU_8087 - opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) +opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64) #endif opFPU(iw, uint16_t, 16, t, geteaw, (double) (int16_t) t, _i16) #ifndef FPU_8087 - opFPU(iw, uint16_t, 32, t, geteaw, (double) (int16_t) t, _i16) +opFPU(iw, uint16_t, 32, t, geteaw, (double) (int16_t) t, _i16) #endif opFPU(il, uint32_t, 16, t, geteal, (double) (int32_t) t, _i32) #ifndef FPU_8087 - opFPU(il, uint32_t, 32, t, geteal, (double) (int32_t) t, _i32) +opFPU(il, uint32_t, 32, t, geteal, (double) (int32_t) t, _i32) #endif - // clang-format on +// clang-format on - static int opFADD(uint32_t fetchdat) +static int opFADD(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; @@ -184,11 +184,11 @@ opFCOM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (ST(0) == ST(fetchdat & 7)) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; else if (ST(0) < ST(fetchdat & 7)) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); return 0; @@ -199,7 +199,7 @@ opFCOMP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7)); x87_pop(); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); @@ -213,11 +213,11 @@ opFCOMPP(uint32_t fetchdat) uint64_t *p, *q; FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); p = (uint64_t *) &ST(0); q = (uint64_t *) &ST(1); if ((*p == ((uint64_t) 1 << 63) && *q == 0) && (fpu_type >= FPU_287XL)) - cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/ + cpu_state.npxs |= FPU_SW_C0; /*Nasty hack to fix 80387 detection*/ else cpu_state.npxs |= x87_compare(ST(0), ST(1)); @@ -233,7 +233,7 @@ opFUCOMPP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(1)); x87_pop(); x87_pop(); @@ -458,7 +458,7 @@ opFUCOM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); @@ -470,7 +470,7 @@ opFUCOMP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7)); x87_pop(); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); @@ -478,7 +478,7 @@ opFUCOMP(uint32_t fetchdat) return 0; } -# ifndef OPS_286_386 +#ifndef OPS_286_386 static int opFUCOMI(uint32_t fetchdat) { diff --git a/src/cpu/x87_ops_misc.h b/src/cpu/x87_ops_misc.h index d854f83dbd..96750468a3 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/cpu/x87_ops_misc.h @@ -78,7 +78,11 @@ opFINIT(uint32_t fetchdat) cpu_state.npxc = 0x37F; #endif codegen_set_rounding_mode(X87_ROUNDING_NEAREST); +#ifdef FPU_8087 + cpu_state.npxs &= 0x4700; +#else cpu_state.npxs = 0; +#endif p = (uint64_t *) cpu_state.tag; #ifdef USE_NEW_DYNAREC *p = 0; @@ -406,7 +410,11 @@ FSAVE(void) cpu_state.npxc = 0x37F; codegen_set_rounding_mode(X87_ROUNDING_NEAREST); +#ifdef FPU_8087 + cpu_state.npxs &= 0x4700; +#else cpu_state.npxs = 0; +#endif p = (uint64_t *) cpu_state.tag; #ifdef USE_NEW_DYNAREC *p = 0; @@ -536,11 +544,11 @@ opFTST(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (ST(0) == 0.0) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; else if (ST(0) < 0.0) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); return 0; @@ -551,20 +559,20 @@ opFXAM(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); #ifdef USE_NEW_DYNAREC if (cpu_state.tag[cpu_state.TOP & 7] == TAG_EMPTY) - cpu_state.npxs |= (C0 | C3); + cpu_state.npxs |= (FPU_SW_C0 | FPU_SW_C3); #else if (cpu_state.tag[cpu_state.TOP & 7] == 3) - cpu_state.npxs |= (C0 | C3); + cpu_state.npxs |= (FPU_SW_C0 | FPU_SW_C3); #endif else if (ST(0) == 0.0) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; else - cpu_state.npxs |= C2; + cpu_state.npxs |= FPU_SW_C2; if (ST(0) < 0.0) - cpu_state.npxs |= C1; + cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fxam) : (x87_timings.fxam * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fxam) : (x87_concurrency.fxam * cpu_multi)); return 0; @@ -694,7 +702,7 @@ opFPTAN(uint32_t fetchdat) ST(0) = tan(ST(0)); FP_TAG_VALID; x87_push(1.0); - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fptan) : (x87_timings.fptan * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fptan) : (x87_concurrency.fptan * cpu_multi)); return 0; @@ -752,13 +760,13 @@ opFPREM(uint32_t fetchdat) temp64 = (int64_t) (ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double) temp64); FP_TAG_VALID; - cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); if (temp64 & 4) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; if (temp64 & 2) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; if (temp64 & 1) - cpu_state.npxs |= C1; + cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem) : (x87_timings.fprem * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem) : (x87_concurrency.fprem * cpu_multi)); return 0; @@ -773,13 +781,13 @@ opFPREM1(uint32_t fetchdat) temp64 = (int64_t) (ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double) temp64); FP_TAG_VALID; - cpu_state.npxs &= ~(C0 | C1 | C2 | C3); + cpu_state.npxs &= ~(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); if (temp64 & 4) - cpu_state.npxs |= C0; + cpu_state.npxs |= FPU_SW_C0; if (temp64 & 2) - cpu_state.npxs |= C3; + cpu_state.npxs |= FPU_SW_C3; if (temp64 & 1) - cpu_state.npxs |= C1; + cpu_state.npxs |= FPU_SW_C1; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fprem1) : (x87_timings.fprem1 * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fprem1) : (x87_concurrency.fprem1 * cpu_multi)); return 0; @@ -808,7 +816,7 @@ opFSINCOS(uint32_t fetchdat) ST(0) = sin(td); FP_TAG_VALID; x87_push(cos(td)); - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsincos) : (x87_timings.fsincos * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsincos) : (x87_concurrency.fsincos * cpu_multi)); return 0; @@ -853,7 +861,7 @@ opFSIN(uint32_t fetchdat) cpu_state.pc++; ST(0) = sin(ST(0)); FP_TAG_VALID; - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); return 0; @@ -866,7 +874,7 @@ opFCOS(uint32_t fetchdat) cpu_state.pc++; ST(0) = cos(ST(0)); FP_TAG_VALID; - cpu_state.npxs &= ~C2; + cpu_state.npxs &= ~FPU_SW_C2; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fsin_cos) : (x87_timings.fsin_cos * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fsin_cos) : (x87_concurrency.fsin_cos * cpu_multi)); return 0; diff --git a/src/cpu/x87_ops_sf.h b/src/cpu/x87_ops_sf.h index 137919fa97..31416447e8 100644 --- a/src/cpu/x87_ops_sf.h +++ b/src/cpu/x87_ops_sf.h @@ -240,6 +240,7 @@ sf_FLDCW_a16(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); tempw = geteaw(); @@ -265,6 +266,7 @@ sf_FLDCW_a32(uint32_t fetchdat) uint16_t tempw; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); tempw = geteaw(); @@ -375,12 +377,13 @@ sf_FRSTOR_a16(uint32_t fetchdat) int offset; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); offset = fpu_load_environment(); for (int n = 0; n < 8; n++) { - tmp.fraction = readmemq(easeg, offset + (n * 10)); - tmp.exp = readmemw(easeg, offset + (n * 10) + 8); + tmp.signif = readmemq(easeg, offset + (n * 10)); + tmp.signExp = readmemw(easeg, offset + (n * 10) + 8); FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n); } CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); @@ -395,12 +398,13 @@ sf_FRSTOR_a32(uint32_t fetchdat) int offset; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); offset = fpu_load_environment(); for (int n = 0; n < 8; n++) { - tmp.fraction = readmemq(easeg, offset + (n * 10)); - tmp.exp = readmemw(easeg, offset + (n * 10) + 8); + tmp.signif = readmemq(easeg, offset + (n * 10)); + tmp.signExp = readmemw(easeg, offset + (n * 10) + 8); FPU_save_regi_tag(tmp, IS_TAG_EMPTY(n) ? X87_TAG_EMPTY : FPU_tagof(tmp), n); } CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.frstor) : (x87_timings.frstor * cpu_multi)); @@ -422,16 +426,17 @@ sf_FNSAVE_a16(uint32_t fetchdat) /* save all registers in stack order. */ for (int m = 0; m < 8; m++) { stn = FPU_read_regi(m); - writememq(easeg, offset + (m * 10), stn.fraction); - writememw(easeg, offset + (m * 10) + 8, stn.exp); + writememq(easeg, offset + (m * 10), stn.signif); + writememw(easeg, offset + (m * 10) + 8, stn.signExp); } #ifdef FPU_8087 - fpu_state.swd = 0x3FF; + fpu_state.cwd = 0x3FF; + fpu_state.swd &= 0x4700; #else fpu_state.cwd = 0x37F; -#endif fpu_state.swd = 0; +#endif fpu_state.tos = 0; fpu_state.tag = 0xffff; cpu_state.ismmx = 0; @@ -458,12 +463,12 @@ sf_FNSAVE_a32(uint32_t fetchdat) /* save all registers in stack order. */ for (int m = 0; m < 8; m++) { stn = FPU_read_regi(m); - writememq(easeg, offset + (m * 10), stn.fraction); - writememw(easeg, offset + (m * 10) + 8, stn.exp); + writememq(easeg, offset + (m * 10), stn.signif); + writememw(easeg, offset + (m * 10) + 8, stn.signExp); } # ifdef FPU_8087 - fpu_state.swd = 0x3FF; + fpu_state.cwd = 0x3FF; # else fpu_state.cwd = 0x37F; # endif @@ -500,10 +505,11 @@ sf_FNINIT(uint32_t fetchdat) cpu_state.pc++; #ifdef FPU_8087 fpu_state.cwd = 0x3FF; + fpu_state.swd &= 0x4700; #else fpu_state.cwd = 0x37F; -#endif fpu_state.swd = 0; +#endif fpu_state.tos = 0; fpu_state.tag = 0xffff; fpu_state.foo = 0; @@ -524,6 +530,7 @@ sf_FLDENV_a16(uint32_t fetchdat) int tag; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); fpu_load_environment(); @@ -546,6 +553,7 @@ sf_FLDENV_a32(uint32_t fetchdat) int tag; FP_ENTER(); + FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); fpu_load_environment(); @@ -600,6 +608,7 @@ static int sf_FNOP(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fnop) : (x87_timings.fnop * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fnop) : (x87_concurrency.fnop * cpu_multi)); diff --git a/src/cpu/x87_ops_sf_arith.h b/src/cpu/x87_ops_sf_arith.h index 5144062bb9..edbd64dcf3 100644 --- a/src/cpu/x87_ops_sf_arith.h +++ b/src/cpu/x87_ops_sf_arith.h @@ -1,8 +1,8 @@ #define sf_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ static int sf_FADD##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -19,9 +19,9 @@ status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) \ - result = floatx80_add(a, use_var, &status); \ + result = extF80_add(a, use_var, &status); \ \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -31,8 +31,8 @@ next_ins: } \ static int sf_FDIV##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -49,9 +49,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) { \ - result = floatx80_div(a, use_var, &status); \ + result = extF80_div(a, use_var, &status); \ } \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -61,8 +61,8 @@ next_ins: } \ static int sf_FDIVR##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -79,9 +79,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) { \ - result = floatx80_div(use_var, a, &status); \ + result = extF80_div(use_var, a, &status); \ } \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -91,8 +91,8 @@ next_ins: } \ static int sf_FMUL##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -109,9 +109,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) { \ - result = floatx80_mul(a, use_var, &status); \ + result = extF80_mul(a, use_var, &status); \ } \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -121,8 +121,8 @@ next_ins: } \ static int sf_FSUB##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -139,9 +139,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) \ - result = floatx80_sub(a, use_var, &status); \ + result = extF80_sub(a, use_var, &status); \ \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -151,8 +151,8 @@ next_ins: } \ static int sf_FSUBR##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a, result; \ - struct float_status_t status; \ + floatx80 a, result; \ + struct softfloat_status_t status; \ optype temp; \ FP_ENTER(); \ FPU_check_pending_exceptions(); \ @@ -169,9 +169,9 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (!is_nan) \ - result = floatx80_sub(use_var, a, &status); \ + result = extF80_sub(use_var, a, &status); \ \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_save_regi(result, 0); \ \ next_ins: \ @@ -181,31 +181,31 @@ next_ins: } // clang-format off -sf_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) +sf_FPU(s, float32, 16, temp, geteal(), f32_to_extF80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) #ifndef FPU_8087 -sf_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) +sf_FPU(s, float32, 32, temp, geteal(), f32_to_extF80(temp, &status), FPU_handle_NaN32(a, temp, &result, &status), _32) #endif -sf_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) +sf_FPU(d, float64, 16, temp, geteaq(), f64_to_extF80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) #ifndef FPU_8087 -sf_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) +sf_FPU(d, float64, 32, temp, geteaq(), f64_to_extF80(temp, &status), FPU_handle_NaN64(a, temp, &result, &status), _64) #endif -sf_FPU(iw, uint16_t, 16, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16) +sf_FPU(iw, uint16_t, 16, temp, geteaw(), i32_to_extF80((int16_t)temp), 0, _i16) #ifndef FPU_8087 -sf_FPU(iw, uint16_t, 32, temp, geteaw(), int32_to_floatx80((int16_t)temp), 0, _i16) +sf_FPU(iw, uint16_t, 32, temp, geteaw(), i32_to_extF80((int16_t)temp), 0, _i16) #endif -sf_FPU(il, uint32_t, 16, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32) +sf_FPU(il, uint32_t, 16, temp, geteal(), i32_to_extF80((int32_t)temp), 0, _i32) #ifndef FPU_8087 -sf_FPU(il, uint32_t, 32, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i32) +sf_FPU(il, uint32_t, 32, temp, geteal(), i32_to_extF80((int32_t)temp), 0, _i32) #endif - // clang-format on +// clang-format on - static int sf_FADD_st0_stj(uint32_t fetchdat) +static int sf_FADD_st0_stj(uint32_t fetchdat) { floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); FPU_check_pending_exceptions(); @@ -218,9 +218,9 @@ sf_FPU(il, uint32_t, 32, temp, geteal(), int32_to_floatx80((int32_t)temp), 0, _i status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_add(a, b, &status); + result = extF80_add(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -234,7 +234,7 @@ sf_FADD_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); FPU_check_pending_exceptions(); @@ -247,9 +247,9 @@ sf_FADD_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_add(a, b, &status); + result = extF80_add(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, fetchdat & 7); next_ins: @@ -264,7 +264,7 @@ sf_FADDP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); FPU_check_pending_exceptions(); @@ -277,9 +277,9 @@ sf_FADDP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_add(a, b, &status); + result = extF80_add(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -296,9 +296,10 @@ sf_FDIV_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -308,9 +309,9 @@ sf_FDIV_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -325,9 +326,10 @@ sf_FDIV_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -337,9 +339,9 @@ sf_FDIV_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, fetchdat & 7); next_ins: @@ -353,9 +355,10 @@ sf_FDIVP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -365,9 +368,9 @@ sf_FDIVP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -384,9 +387,10 @@ sf_FDIVR_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -396,9 +400,9 @@ sf_FDIVR_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -412,9 +416,10 @@ sf_FDIVR_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -424,9 +429,9 @@ sf_FDIVR_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, fetchdat & 7); next_ins: @@ -440,9 +445,10 @@ sf_FDIVRP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -452,9 +458,9 @@ sf_FDIVRP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_div(a, b, &status); + result = extF80_div(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -471,9 +477,10 @@ sf_FMUL_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -483,9 +490,9 @@ sf_FMUL_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_mul(a, b, &status); + result = extF80_mul(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -500,9 +507,10 @@ sf_FMUL_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -512,9 +520,9 @@ sf_FMUL_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_mul(a, b, &status); + result = extF80_mul(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); } @@ -529,9 +537,10 @@ sf_FMULP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -541,9 +550,9 @@ sf_FMULP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_mul(a, b, &status); + result = extF80_mul(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -560,9 +569,10 @@ sf_FSUB_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -572,9 +582,9 @@ sf_FSUB_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -589,9 +599,10 @@ sf_FSUB_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -601,9 +612,9 @@ sf_FSUB_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); } @@ -618,9 +629,10 @@ sf_FSUBP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -630,9 +642,9 @@ sf_FSUBP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -649,9 +661,10 @@ sf_FSUBR_st0_stj(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -661,9 +674,9 @@ sf_FSUBR_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(fetchdat & 7); b = FPU_read_regi(0); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -678,9 +691,10 @@ sf_FSUBR_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -690,9 +704,9 @@ sf_FSUBR_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); } @@ -707,9 +721,10 @@ sf_FSUBRP_sti_st0(uint32_t fetchdat) floatx80 a; floatx80 b; floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { @@ -719,9 +734,9 @@ sf_FSUBRP_sti_st0(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - result = floatx80_sub(a, b, &status); + result = extF80_sub(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, fetchdat & 7); FPU_pop(); } @@ -736,9 +751,10 @@ static int sf_FSQRT(uint32_t fetchdat) { floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { @@ -746,9 +762,9 @@ sf_FSQRT(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = floatx80_sqrt(FPU_read_regi(0), &status); + result = extF80_sqrt(FPU_read_regi(0), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } @@ -762,9 +778,10 @@ static int sf_FRNDINT(uint32_t fetchdat) { floatx80 result; - struct float_status_t status; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { @@ -772,9 +789,9 @@ sf_FRNDINT(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = floatx80_round_to_int(FPU_read_regi(0), &status); + result = extF80_roundToInt_normal(FPU_read_regi(0), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 0); } diff --git a/src/cpu/x87_ops_sf_compare.h b/src/cpu/x87_ops_sf_compare.h index 6b4c1cb62b..c4a38b3755 100644 --- a/src/cpu/x87_ops_sf_compare.h +++ b/src/cpu/x87_ops_sf_compare.h @@ -1,11 +1,12 @@ #define cmp_FPU(name, optype, a_size, load_var, rw, use_var, is_nan, cycle_postfix) \ static int sf_FCOM##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a; \ - int rc; \ - struct float_status_t status; \ - optype temp; \ + floatx80 a; \ + int rc; \ + struct softfloat_status_t status; \ + optype temp; \ FP_ENTER(); \ + FPU_check_pending_exceptions(); \ fetch_ea_##a_size(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = rw; \ @@ -14,19 +15,19 @@ clear_C1(); \ if (IS_TAG_EMPTY(0)) { \ FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \ - setcc(C0 | C2 | C3); \ + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ goto next_ins; \ } \ status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (is_nan) { \ - rc = float_relation_unordered; \ - float_raise(&status, float_flag_invalid); \ + rc = softfloat_relation_unordered; \ + softfloat_raiseFlags(&status, softfloat_flag_invalid); \ } else { \ - rc = floatx80_compare_two(a, use_var, &status); \ + rc = extF80_compare_normal(a, use_var, &status); \ } \ setcc(FPU_status_word_flags_fpu_compare(rc)); \ - FPU_exception(fetchdat, status.float_exception_flags, 0); \ + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); \ \ next_ins: \ CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom##cycle_postfix) : ((x87_timings.fcom##cycle_postfix) * cpu_multi)); \ @@ -35,11 +36,12 @@ next_ins: } \ static int sf_FCOMP##name##_a##a_size(uint32_t fetchdat) \ { \ - floatx80 a; \ - int rc; \ - struct float_status_t status; \ - optype temp; \ + floatx80 a; \ + int rc; \ + struct softfloat_status_t status; \ + optype temp; \ FP_ENTER(); \ + FPU_check_pending_exceptions(); \ fetch_ea_##a_size(fetchdat); \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = rw; \ @@ -48,7 +50,7 @@ next_ins: clear_C1(); \ if (IS_TAG_EMPTY(0)) { \ FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); \ - setcc(C0 | C2 | C3); \ + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); \ if (is_IA_masked()) \ FPU_pop(); \ \ @@ -57,13 +59,13 @@ next_ins: status = i387cw_to_softfloat_status_word(i387_get_control_word()); \ a = FPU_read_regi(0); \ if (is_nan) { \ - rc = float_relation_unordered; \ - float_raise(&status, float_flag_invalid); \ + rc = softfloat_relation_unordered; \ + softfloat_raiseFlags(&status, softfloat_flag_invalid); \ } else { \ - rc = floatx80_compare_two(a, use_var, &status); \ + rc = extF80_compare_normal(a, use_var, &status); \ } \ setcc(FPU_status_word_flags_fpu_compare(rc)); \ - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) \ + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) \ FPU_pop(); \ \ next_ins: \ @@ -73,46 +75,48 @@ next_ins: } // clang-format off -cmp_FPU(s, float32, 16, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32) +cmp_FPU(s, float32, 16, temp, geteal(), f32_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f32_isNaN(temp), _32) #ifndef FPU_8087 -cmp_FPU(s, float32, 32, temp, geteal(), float32_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float32_is_nan(temp), _32) +cmp_FPU(s, float32, 32, temp, geteal(), f32_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f32_isNaN(temp), _32) #endif -cmp_FPU(d, float64, 16, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64) +cmp_FPU(d, float64, 16, temp, geteaq(), f64_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f64_isNaN(temp), _64) #ifndef FPU_8087 -cmp_FPU(d, float64, 32, temp, geteaq(), float64_to_floatx80(temp, &status), floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(temp), _64) +cmp_FPU(d, float64, 32, temp, geteaq(), f64_to_extF80(temp, &status), extF80_isNaN(a) || extF80_isUnsupported(a) || f64_isNaN(temp), _64) #endif -cmp_FPU(iw, int16_t, 16, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16) +cmp_FPU(iw, int16_t, 16, temp, (int16_t)geteaw(), i32_to_extF80((int32_t)temp), 0, _i16) #ifndef FPU_8087 -cmp_FPU(iw, int16_t, 32, temp, (int16_t)geteaw(), int32_to_floatx80((int32_t)temp), 0, _i16) +cmp_FPU(iw, int16_t, 32, temp, (int16_t)geteaw(), i32_to_extF80((int32_t)temp), 0, _i16) #endif -cmp_FPU(il, int32_t, 16, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32) +cmp_FPU(il, int32_t, 16, temp, (int32_t)geteal(), i32_to_extF80(temp), 0, _i32) #ifndef FPU_8087 -cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i32) +cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), i32_to_extF80(temp), 0, _i32) #endif - // clang-format on +// clang-format on - static int sf_FCOM_sti(uint32_t fetchdat) +static int +sf_FCOM_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); @@ -123,17 +127,18 @@ cmp_FPU(il, int32_t, 32, temp, (int32_t)geteal(), int32_to_floatx80(temp), 0, _i static int sf_FCOMP_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) { FPU_pop(); } @@ -142,9 +147,9 @@ sf_FCOMP_sti(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); } @@ -157,17 +162,18 @@ sf_FCOMP_sti(uint32_t fetchdat) static int sf_FCOMPP(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) { FPU_pop(); FPU_pop(); @@ -177,9 +183,9 @@ sf_FCOMPP(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(1); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_pop(); } @@ -194,17 +200,18 @@ sf_FCOMPP(uint32_t fetchdat) static int sf_FUCOMPP(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) { FPU_pop(); FPU_pop(); @@ -214,9 +221,9 @@ sf_FUCOMPP(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(1); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_pop(); } @@ -227,16 +234,17 @@ sf_FUCOMPP(uint32_t fetchdat) return 0; } -# ifndef OPS_286_386 +#ifndef OPS_286_386 static int sf_FCOMI_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -248,9 +256,9 @@ sf_FCOMI_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); FPU_write_eflags_fpu_compare(rc); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fcom) : (x87_timings.fcom * cpu_multi)); @@ -260,12 +268,13 @@ sf_FCOMI_st0_stj(uint32_t fetchdat) static int sf_FCOMIP_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -280,9 +289,9 @@ sf_FCOMIP_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_two(a, b, &status); + rc = extF80_compare_normal(a, b, &status); FPU_write_eflags_fpu_compare(rc); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); } @@ -291,30 +300,31 @@ sf_FCOMIP_st0_stj(uint32_t fetchdat) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi)); return 0; } -# endif +#endif static int sf_FUCOM_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); @@ -325,17 +335,18 @@ sf_FUCOM_sti(uint32_t fetchdat) static int sf_FUCOMP_sti(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(fetchdat & 7)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); if (is_IA_masked()) FPU_pop(); @@ -344,9 +355,9 @@ sf_FUCOMP_sti(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_pop(); next_ins: @@ -359,12 +370,13 @@ sf_FUCOMP_sti(uint32_t fetchdat) static int sf_FUCOMI_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -376,9 +388,9 @@ sf_FUCOMI_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); FPU_write_eflags_fpu_compare(rc); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); next_ins: CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.fucom) : (x87_timings.fucom * cpu_multi)); @@ -388,12 +400,13 @@ sf_FUCOMI_st0_stj(uint32_t fetchdat) static int sf_FUCOMIP_st0_stj(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - struct float_status_t status; - int rc; + floatx80 a; + floatx80 b; + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; flags_rebuild(); clear_C1(); @@ -408,9 +421,9 @@ sf_FUCOMIP_st0_stj(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); b = FPU_read_regi(fetchdat & 7); - rc = floatx80_compare_quiet(a, b, &status); + rc = extF80_compare_quiet(a, b, &status); FPU_write_eflags_fpu_compare(rc); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_pop(); next_ins: @@ -418,26 +431,28 @@ sf_FUCOMIP_st0_stj(uint32_t fetchdat) CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fucom) : (x87_concurrency.fucom * cpu_multi)); return 0; } -# endif +#endif #endif static int sf_FTST(uint32_t fetchdat) { - int rc; - struct float_status_t status; + const floatx80 Const_Z = packFloatx80(0, 0x0000, 0); + struct softfloat_status_t status; + int rc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); - setcc(C0 | C2 | C3); + setcc(FPU_SW_C0 | FPU_SW_C2 | FPU_SW_C3); } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - rc = floatx80_compare_two(FPU_read_regi(0), Const_Z, &status); + rc = extF80_compare_normal(FPU_read_regi(0), Const_Z, &status); setcc(FPU_status_word_flags_fpu_compare(rc)); - FPU_exception(fetchdat, status.float_exception_flags, 0); + FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); } CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ftst) : (x87_timings.ftst * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ftst) : (x87_concurrency.ftst * cpu_multi)); @@ -447,45 +462,45 @@ sf_FTST(uint32_t fetchdat) static int sf_FXAM(uint32_t fetchdat) { - floatx80 reg; - int sign; - float_class_t aClass; + floatx80 reg; + int sign; + softfloat_class_t aClass; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; reg = FPU_read_regi(0); - sign = floatx80_sign(reg); + sign = extF80_sign(reg); /* * Examine the contents of the ST(0) register and sets the condition * code flags C0, C2 and C3 in the FPU status word to indicate the * class of value or number in the register. */ if (IS_TAG_EMPTY(0)) { - setcc(C3 | C1 | C0); + setcc(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C3); } else { - aClass = floatx80_class(reg); + aClass = extF80_class(reg); switch (aClass) { - case float_zero: - setcc(C3 | C1); + case softfloat_zero: + setcc(FPU_SW_C1 | FPU_SW_C3); break; - case float_SNaN: - case float_QNaN: + case softfloat_SNaN: + case softfloat_QNaN: // unsupported handled as NaNs - if (floatx80_is_unsupported(reg)) { - setcc(C1); - } else { - setcc(C1 | C0); - } + if (extF80_isUnsupported(reg)) + setcc(FPU_SW_C1); + else + setcc(FPU_SW_C0 | FPU_SW_C1); break; - case float_negative_inf: - case float_positive_inf: - setcc(C2 | C1 | C0); + case softfloat_negative_inf: + case softfloat_positive_inf: + setcc(FPU_SW_C0 | FPU_SW_C1 | FPU_SW_C2); break; - case float_denormal: - setcc(C3 | C2 | C1); + case softfloat_denormal: + setcc(FPU_SW_C1 | FPU_SW_C2 | FPU_SW_C3); break; - case float_normalized: - setcc(C2 | C1); + case softfloat_normalized: + setcc(FPU_SW_C1 | FPU_SW_C2); break; } } diff --git a/src/cpu/x87_ops_sf_const.h b/src/cpu/x87_ops_sf_const.h index 0808cbae82..19cc401f57 100644 --- a/src/cpu/x87_ops_sf_const.h +++ b/src/cpu/x87_ops_sf_const.h @@ -3,18 +3,11 @@ */ #define DOWN_OR_CHOP() (fpu_state.cwd & FPU_CW_RC & FPU_RC_DOWN) -static __inline floatx80 -FPU_round_const(const floatx80 a, int adj) -{ - floatx80 result = a; - result.fraction += adj; - return result; -} - static int sf_FLDL2T(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -32,6 +25,7 @@ static int sf_FLDL2E(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -49,6 +43,7 @@ static int sf_FLDPI(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -66,6 +61,7 @@ static int sf_FLDEG2(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -83,6 +79,7 @@ static int sf_FLDLN2(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -100,6 +97,7 @@ static int sf_FLD1(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) @@ -117,6 +115,7 @@ static int sf_FLDZ(uint32_t fetchdat) { FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (!IS_TAG_EMPTY(-1)) diff --git a/src/cpu/x87_ops_sf_load_store.h b/src/cpu/x87_ops_sf_load_store.h index 228d9fc061..69249016e6 100644 --- a/src/cpu/x87_ops_sf_load_store.h +++ b/src/cpu/x87_ops_sf_load_store.h @@ -38,10 +38,10 @@ sf_FILDiw_a16(uint32_t fetchdat) if (cpu_state.abrt) return 1; clear_C1(); - if (!IS_TAG_EMPTY(-1)) { + if (!IS_TAG_EMPTY(-1)) FPU_stack_overflow(fetchdat); - } else { - result = int32_to_floatx80(temp); + else { + result = i32_to_extF80(temp); FPU_push(); FPU_save_regi(result, 0); } @@ -67,7 +67,7 @@ sf_FILDiw_a32(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int32_to_floatx80(temp); + result = i32_to_extF80(temp); FPU_push(); FPU_save_regi(result, 0); } @@ -94,7 +94,7 @@ sf_FILDil_a16(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int32_to_floatx80(templ); + result = i32_to_extF80(templ); FPU_push(); FPU_save_regi(result, 0); } @@ -120,7 +120,7 @@ sf_FILDil_a32(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int32_to_floatx80(templ); + result = i32_to_extF80(templ); FPU_push(); FPU_save_regi(result, 0); } @@ -147,7 +147,7 @@ sf_FILDiq_a16(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int64_to_floatx80(temp64); + result = i64_to_extF80(temp64); FPU_push(); FPU_save_regi(result, 0); } @@ -173,7 +173,7 @@ sf_FILDiq_a32(uint32_t fetchdat) if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - result = int64_to_floatx80(temp64); + result = i64_to_extF80(temp64); FPU_push(); FPU_save_regi(result, 0); } @@ -187,40 +187,36 @@ static int sf_FBLD_PACKED_BCD_a16(uint32_t fetchdat) { floatx80 result; - uint16_t load_reg_hi = 0xffff; - uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); - int64_t load_val = 0ULL; - uint64_t power; - int sign; + uint16_t load_reg_hi; + uint64_t load_reg_lo; + int64_t val64 = 0; + int64_t scale = 1; FP_ENTER(); FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_hi = readmemw(easeg, (cpu_state.eaaddr + 8) & 0xffff); load_reg_lo = readmemq(easeg, cpu_state.eaaddr); - load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - sign = (load_reg_hi & 0x8000) != 0; - load_val = 0ULL; - power = 1; - for (int i = 0; i < 16; i++) { - load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + for (int n = 0; n < 16; n++) { + val64 += ((load_reg_lo & 0x0f) * scale); load_reg_lo >>= 4; - power *= 10; + scale *= 10; } - for (int i = 0; i < 2; i++) { - load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; - load_reg_hi >>= 4; - power *= 10; - } - if (sign) - load_val = -load_val; - result = int64_to_floatx80(load_val); + val64 += ((load_reg_hi & 0x0f) * scale); + val64 += (((load_reg_hi >> 4) & 0x0f) * scale * 10); + + result = (floatx80) i64_to_extF80(val64); + + if (load_reg_hi & 0x8000) + floatx80_chs(result); + FPU_push(); FPU_save_regi(result, 0); } @@ -233,40 +229,36 @@ static int sf_FBLD_PACKED_BCD_a32(uint32_t fetchdat) { floatx80 result; - uint16_t load_reg_hi = 0xffff; - uint64_t load_reg_lo = BX_CONST64(0xC000000000000000); - int64_t load_val = 0ULL; - uint64_t power; - int sign; + uint16_t load_reg_hi; + uint64_t load_reg_lo; + int64_t val64 = 0; + int64_t scale = 1; FP_ENTER(); FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); + load_reg_hi = readmemw(easeg, (cpu_state.eaaddr + 8) & 0xffff); load_reg_lo = readmemq(easeg, cpu_state.eaaddr); - load_reg_hi = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); } else { - sign = (load_reg_hi & 0x8000) != 0; - load_val = 0ULL; - power = 1; - for (int i = 0; i < 16; i++) { - load_val += ((uint64_t) (load_reg_lo & 0xf)) * power; + for (int n = 0; n < 16; n++) { + val64 += ((load_reg_lo & 0x0f) * scale); load_reg_lo >>= 4; - power *= 10; + scale *= 10; } - for (int i = 0; i < 2; i++) { - load_val += ((uint64_t) (load_reg_hi & 0xf)) * power; - load_reg_hi >>= 4; - power *= 10; - } - if (sign) - load_val = -load_val; - result = int64_to_floatx80(load_val); + val64 += ((load_reg_hi & 0x0f) * scale); + val64 += (((load_reg_hi >> 4) & 0x0f) * scale * 10); + + result = (floatx80) i64_to_extF80(val64); + + if (load_reg_hi & 0x8000) + floatx80_chs(result); + FPU_push(); FPU_save_regi(result, 0); } @@ -279,10 +271,10 @@ sf_FBLD_PACKED_BCD_a32(uint32_t fetchdat) static int sf_FLDs_a16(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float32 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float32 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -297,8 +289,8 @@ sf_FLDs_a16(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float32_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f32_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -313,10 +305,10 @@ sf_FLDs_a16(uint32_t fetchdat) static int sf_FLDs_a32(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float32 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float32 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -331,8 +323,8 @@ sf_FLDs_a32(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float32_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f32_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -348,10 +340,10 @@ sf_FLDs_a32(uint32_t fetchdat) static int sf_FLDd_a16(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float64 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float64 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -366,8 +358,8 @@ sf_FLDd_a16(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float64_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f64_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -382,10 +374,10 @@ sf_FLDd_a16(uint32_t fetchdat) static int sf_FLDd_a32(uint32_t fetchdat) { - struct float_status_t status; - floatx80 result; - float64 load_reg; - unsigned unmasked; + struct softfloat_status_t status; + floatx80 result; + float64 load_reg; + unsigned unmasked; FP_ENTER(); FPU_check_pending_exceptions(); @@ -400,8 +392,8 @@ sf_FLDd_a32(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = float64_to_floatx80(load_reg, &status); - unmasked = FPU_exception(fetchdat, status.float_exception_flags, 0); + result = f64_to_extF80(load_reg, &status); + unmasked = FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0); if (!(unmasked & FPU_CW_Invalid)) { FPU_push(); FPU_save_regi(result, 0); @@ -423,10 +415,11 @@ sf_FLDe_a16(uint32_t fetchdat) FPU_check_pending_exceptions(); fetch_ea_16(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); - result.fraction = readmemq(easeg, cpu_state.eaaddr); - result.exp = readmemw(easeg, cpu_state.eaaddr + 8); + result.signif = readmemq(easeg, cpu_state.eaaddr); + result.signExp = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; + clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); @@ -448,10 +441,11 @@ sf_FLDe_a32(uint32_t fetchdat) FPU_check_pending_exceptions(); fetch_ea_32(fetchdat); SEG_CHECK_READ(cpu_state.ea_seg); - result.fraction = readmemq(easeg, cpu_state.eaaddr); - result.exp = readmemw(easeg, cpu_state.eaaddr + 8); + result.signif = readmemq(easeg, cpu_state.eaaddr); + result.signExp = readmemw(easeg, cpu_state.eaaddr + 8); if (cpu_state.abrt) return 1; + clear_C1(); if (!IS_TAG_EMPTY(-1)) { FPU_stack_overflow(fetchdat); @@ -484,9 +478,8 @@ sf_FLD_sti(uint32_t fetchdat) FPU_exception(fetchdat, FPU_EX_Stack_Underflow, 0); if (!is_IA_masked()) goto next_ins; - } else { + } else sti_reg = FPU_read_regi(fetchdat & 7); - } FPU_push(); FPU_save_regi(sti_reg, 0); @@ -500,9 +493,9 @@ sf_FLD_sti(uint32_t fetchdat) static int sf_FISTiw_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -516,8 +509,8 @@ sf_FISTiw_a16(uint32_t fetchdat) } } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -535,9 +528,9 @@ sf_FISTiw_a16(uint32_t fetchdat) static int sf_FISTiw_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -550,8 +543,8 @@ sf_FISTiw_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -569,9 +562,9 @@ sf_FISTiw_a32(uint32_t fetchdat) static int sf_FISTPiw_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -584,8 +577,8 @@ sf_FISTPiw_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -606,9 +599,9 @@ sf_FISTPiw_a16(uint32_t fetchdat) static int sf_FISTPiw_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int16_t save_reg = int16_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int16_t save_reg = int16_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -621,8 +614,8 @@ sf_FISTPiw_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int16(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i16(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -643,9 +636,9 @@ sf_FISTPiw_a32(uint32_t fetchdat) static int sf_FISTil_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -658,8 +651,8 @@ sf_FISTil_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -677,9 +670,9 @@ sf_FISTil_a16(uint32_t fetchdat) static int sf_FISTil_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -692,8 +685,8 @@ sf_FISTil_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -711,9 +704,9 @@ sf_FISTil_a32(uint32_t fetchdat) static int sf_FISTPil_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -726,8 +719,8 @@ sf_FISTPil_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -748,9 +741,9 @@ sf_FISTPil_a16(uint32_t fetchdat) static int sf_FISTPil_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int32_t save_reg = int32_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int32_t save_reg = int32_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -763,8 +756,8 @@ sf_FISTPil_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i32_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -785,9 +778,9 @@ sf_FISTPil_a32(uint32_t fetchdat) static int sf_FISTPiq_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int64_t save_reg = int64_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int64_t save_reg = int64_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -800,8 +793,8 @@ sf_FISTPiq_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_i64_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -822,9 +815,9 @@ sf_FISTPiq_a16(uint32_t fetchdat) static int sf_FISTPiq_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - int64_t save_reg = int64_indefinite; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + int64_t save_reg = int64_indefinite; FP_ENTER(); FPU_check_pending_exceptions(); @@ -837,8 +830,8 @@ sf_FISTPiq_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_int64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_i64_normal(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case origial FPU_SW must be kept @@ -859,13 +852,13 @@ sf_FISTPiq_a32(uint32_t fetchdat) static int sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - uint16_t save_reg_hi = 0xffff; - uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); - floatx80 reg; - int64_t save_val; - int sign; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + uint16_t save_reg_hi = 0xffff; + uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); + floatx80 reg; + int64_t save_val; + int sign; FP_ENTER(); FPU_check_pending_exceptions(); @@ -879,15 +872,15 @@ sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); reg = FPU_read_regi(0); - save_val = floatx80_to_int64(reg, &status); - sign = (reg.exp & 0x8000) != 0; + save_val = extF80_to_i64_normal(reg, &status); + sign = extF80_sign(reg); if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) - status.float_exception_flags = float_flag_invalid; // throw away other flags + softfloat_setFlags(&status, softfloat_flag_invalid); // throw away other flags - if (!(status.float_exception_flags & float_flag_invalid)) { + if (!(status.softfloat_exceptionFlags & softfloat_flag_invalid)) { save_reg_hi = sign ? 0x8000 : 0; save_reg_lo = 0; for (int i = 0; i < 16; i++) { @@ -899,7 +892,7 @@ sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) save_reg_hi += (uint16_t) (save_val % 10) << 4; } /* check for fpu arithmetic exceptions */ - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -923,13 +916,13 @@ sf_FBSTP_PACKED_BCD_a16(uint32_t fetchdat) static int sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - uint16_t save_reg_hi = 0xffff; - uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); - floatx80 reg; - int64_t save_val; - int sign; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + uint16_t save_reg_hi = 0xffff; + uint64_t save_reg_lo = BX_CONST64(0xC000000000000000); + floatx80 reg; + int64_t save_val; + int sign; FP_ENTER(); FPU_check_pending_exceptions(); @@ -943,15 +936,15 @@ sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); reg = FPU_read_regi(0); - save_val = floatx80_to_int64(reg, &status); - sign = (reg.exp & 0x8000) != 0; + save_val = extF80_to_i64_normal(reg, &status); + sign = extF80_sign(reg); if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) - status.float_exception_flags = float_flag_invalid; // throw away other flags + softfloat_setFlags(&status, softfloat_flag_invalid); // throw away other flags - if (!(status.float_exception_flags & float_flag_invalid)) { + if (!(status.softfloat_exceptionFlags & softfloat_flag_invalid)) { save_reg_hi = sign ? 0x8000 : 0; save_reg_lo = 0; for (int i = 0; i < 16; i++) { @@ -963,7 +956,7 @@ sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) save_reg_hi += (uint16_t) (save_val % 10) << 4; } /* check for fpu arithmetic exceptions */ - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -988,9 +981,9 @@ sf_FBSTP_PACKED_BCD_a32(uint32_t fetchdat) static int sf_FSTs_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1003,8 +996,8 @@ sf_FSTs_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -1022,9 +1015,9 @@ sf_FSTs_a16(uint32_t fetchdat) static int sf_FSTs_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1037,8 +1030,8 @@ sf_FSTs_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1056,9 +1049,9 @@ sf_FSTs_a32(uint32_t fetchdat) static int sf_FSTPs_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1071,17 +1064,17 @@ sf_FSTPs_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } // store to the memory might generate an exception, in this case original FPU_SW must be kept swap_values16u(sw, fpu_state.swd); seteal(save_reg); - if (cpu_state.abrt) { + if (cpu_state.abrt) return 1; - } + fpu_state.swd = sw; FPU_pop(); @@ -1094,9 +1087,9 @@ sf_FSTPs_a16(uint32_t fetchdat) static int sf_FSTPs_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float32 save_reg = float32_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float32 save_reg = float32_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1109,8 +1102,8 @@ sf_FSTPs_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float32(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f32(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1118,6 +1111,7 @@ sf_FSTPs_a32(uint32_t fetchdat) seteal(save_reg); if (cpu_state.abrt) return 1; + fpu_state.swd = sw; FPU_pop(); @@ -1131,9 +1125,9 @@ sf_FSTPs_a32(uint32_t fetchdat) static int sf_FSTd_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1146,8 +1140,8 @@ sf_FSTd_a16(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -1165,9 +1159,9 @@ sf_FSTd_a16(uint32_t fetchdat) static int sf_FSTd_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1180,8 +1174,8 @@ sf_FSTd_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1199,9 +1193,9 @@ sf_FSTd_a32(uint32_t fetchdat) static int sf_FSTPd_a16(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1215,8 +1209,8 @@ sf_FSTPd_a16(uint32_t fetchdat) } } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) { + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) { goto next_ins; } } @@ -1225,6 +1219,7 @@ sf_FSTPd_a16(uint32_t fetchdat) seteaq(save_reg); if (cpu_state.abrt) return 1; + fpu_state.swd = sw; FPU_pop(); @@ -1237,9 +1232,9 @@ sf_FSTPd_a16(uint32_t fetchdat) static int sf_FSTPd_a32(uint32_t fetchdat) { - struct float_status_t status; - uint16_t sw = fpu_state.swd; - float64 save_reg = float64_default_nan; + struct softfloat_status_t status; + uint16_t sw = fpu_state.swd; + float64 save_reg = float64_default_nan; FP_ENTER(); FPU_check_pending_exceptions(); @@ -1252,8 +1247,8 @@ sf_FSTPd_a32(uint32_t fetchdat) goto next_ins; } else { status = i387cw_to_softfloat_status_word(i387_get_control_word()); - save_reg = floatx80_to_float64(FPU_read_regi(0), &status); - if (FPU_exception(fetchdat, status.float_exception_flags, 1)) + save_reg = extF80_to_f64(FPU_read_regi(0), &status); + if (FPU_exception(fetchdat, status.softfloat_exceptionFlags, 1)) goto next_ins; } // store to the memory might generate an exception, in this case original FPU_SW must be kept @@ -1261,6 +1256,7 @@ sf_FSTPd_a32(uint32_t fetchdat) seteaq(save_reg); if (cpu_state.abrt) return 1; + fpu_state.swd = sw; FPU_pop(); @@ -1293,8 +1289,8 @@ sf_FSTPe_a16(uint32_t fetchdat) } else { save_reg = FPU_read_regi(0); } - writememq(easeg, cpu_state.eaaddr, save_reg.fraction); - writememw(easeg, cpu_state.eaaddr + 8, save_reg.exp); + writememq(easeg, cpu_state.eaaddr, save_reg.signif); + writememw(easeg, cpu_state.eaaddr + 8, save_reg.signExp); FPU_pop(); next_ins: @@ -1324,8 +1320,8 @@ sf_FSTPe_a32(uint32_t fetchdat) } else { save_reg = FPU_read_regi(0); } - writememq(easeg, cpu_state.eaaddr, save_reg.fraction); - writememw(easeg, cpu_state.eaaddr + 8, save_reg.exp); + writememq(easeg, cpu_state.eaaddr, save_reg.signif); + writememw(easeg, cpu_state.eaaddr + 8, save_reg.signExp); FPU_pop(); next_ins: @@ -1365,7 +1361,7 @@ sf_FSTP_sti(uint32_t fetchdat) cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { - FPU_stack_underflow(fetchdat, fetchdat & 7, 1); + FPU_pop(); } else { st0_reg = FPU_read_regi(0); FPU_save_regi(st0_reg, fetchdat & 7); diff --git a/src/cpu/x87_ops_sf_misc.h b/src/cpu/x87_ops_sf_misc.h index 85f42e6d58..0aab2ec08d 100644 --- a/src/cpu/x87_ops_sf_misc.h +++ b/src/cpu/x87_ops_sf_misc.h @@ -129,6 +129,7 @@ sf_FFREEP_sti(uint32_t fetchdat) FPU_settagi(X87_TAG_EMPTY, fetchdat & 7); if (cpu_state.abrt) return 1; + FPU_pop(); CLOCK_CYCLES_FPU((fpu_type >= FPU_487SX) ? (x87_timings.ffree) : (x87_timings.ffree * cpu_multi)); CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.ffree) : (x87_concurrency.ffree * cpu_multi)); diff --git a/src/cpu/x87_ops_sf_trans.h b/src/cpu/x87_ops_sf_trans.h index 5a99abb4c0..d5aec0110e 100644 --- a/src/cpu/x87_ops_sf_trans.h +++ b/src/cpu/x87_ops_sf_trans.h @@ -1,10 +1,11 @@ static int sf_F2XM1(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0)) { @@ -13,7 +14,7 @@ sf_F2XM1(uint32_t fetchdat) } status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = f2xm1(FPU_read_regi(0), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -25,10 +26,11 @@ sf_F2XM1(uint32_t fetchdat) static int sf_FYL2X(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { @@ -37,7 +39,7 @@ sf_FYL2X(uint32_t fetchdat) } status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = fyl2x(FPU_read_regi(0), FPU_read_regi(1), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_save_regi(result, 0); } @@ -51,11 +53,12 @@ sf_FYL2X(uint32_t fetchdat) static int sf_FPTAN(uint32_t fetchdat) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - floatx80 y; - struct float_status_t status; + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + floatx80 y; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -76,12 +79,12 @@ sf_FPTAN(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (ftan(&y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (floatx80_is_nan(y)) { - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (extF80_isNaN(y)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(y, 0); FPU_push(); FPU_save_regi(y, 0); @@ -89,7 +92,7 @@ sf_FPTAN(uint32_t fetchdat) goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(y, 0); FPU_push(); FPU_save_regi(Const_1, 0); @@ -104,12 +107,13 @@ sf_FPTAN(uint32_t fetchdat) static int sf_FPATAN(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - floatx80 result; - struct float_status_t status; + floatx80 a; + floatx80 b; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { FPU_stack_underflow(fetchdat, 1, 1); @@ -119,7 +123,7 @@ sf_FPATAN(uint32_t fetchdat) b = FPU_read_regi(1); status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = fpatan(a, b, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_pop(); FPU_save_regi(result, 0); } @@ -133,11 +137,15 @@ sf_FPATAN(uint32_t fetchdat) static int sf_FXTRACT(uint32_t fetchdat) { - struct float_status_t status; - floatx80 a; - floatx80 b; + struct softfloat_status_t status; + floatx80 a; + floatx80 b; +#if 0 + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); +#endif FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); @@ -160,8 +168,8 @@ sf_FXTRACT(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word()); a = FPU_read_regi(0); - b = floatx80_extract(&a, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + b = extF80_extract(&a, &status); + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(b, 0); // exponent FPU_push(); FPU_save_regi(a, 0); // fraction @@ -178,15 +186,16 @@ sf_FXTRACT(uint32_t fetchdat) static int sf_FPREM1(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - floatx80 result; - struct float_status_t status; - uint64_t quotient = 0; - int flags; - int cc; + floatx80 a; + floatx80 b; + floatx80 result; + struct softfloat_status_t status; + uint64_t quotient = 0; + int flags; + int cc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -198,18 +207,18 @@ sf_FPREM1(uint32_t fetchdat) a = FPU_read_regi(0); b = FPU_read_regi(1); flags = floatx80_ieee754_remainder(a, b, &result, "ient, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { if (flags >= 0) { cc = 0; if (flags) - cc = C2; + cc = FPU_SW_C2; else { if (quotient & 1) - cc |= C1; + cc |= FPU_SW_C1; if (quotient & 2) - cc |= C3; + cc |= FPU_SW_C3; if (quotient & 4) - cc |= C0; + cc |= FPU_SW_C0; } setcc(cc); } @@ -225,15 +234,16 @@ sf_FPREM1(uint32_t fetchdat) static int sf_FPREM(uint32_t fetchdat) { - floatx80 a; - floatx80 b; - floatx80 result; - struct float_status_t status; - uint64_t quotient = 0; - int flags; - int cc; + floatx80 a; + floatx80 b; + floatx80 result; + struct softfloat_status_t status; + uint64_t quotient = 0; + int flags; + int cc; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -246,18 +256,18 @@ sf_FPREM(uint32_t fetchdat) b = FPU_read_regi(1); // handle unsupported extended double-precision floating encodings flags = floatx80_remainder(a, b, &result, "ient, &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { if (flags >= 0) { cc = 0; if (flags) - cc = C2; + cc = FPU_SW_C2; else { if (quotient & 1) - cc |= C1; + cc |= FPU_SW_C1; if (quotient & 2) - cc |= C3; + cc |= FPU_SW_C3; if (quotient & 4) - cc |= C0; + cc |= FPU_SW_C0; } setcc(cc); } @@ -273,10 +283,11 @@ sf_FPREM(uint32_t fetchdat) static int sf_FYL2XP1(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { @@ -285,7 +296,7 @@ sf_FYL2XP1(uint32_t fetchdat) } status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); result = fyl2xp1(FPU_read_regi(0), FPU_read_regi(1), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(result, 1); FPU_pop(); } @@ -300,13 +311,14 @@ sf_FYL2XP1(uint32_t fetchdat) static int sf_FSINCOS(uint32_t fetchdat) { - const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); - struct float_status_t status; - floatx80 y; - floatx80 sin_y; - floatx80 cos_y; + const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction); + struct softfloat_status_t status; + floatx80 y; + floatx80 sin_y; + floatx80 cos_y; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -327,10 +339,10 @@ sf_FSINCOS(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (fsincos(y, &sin_y, &cos_y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) { + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) { FPU_save_regi(sin_y, 0); FPU_push(); FPU_save_regi(cos_y, 0); @@ -346,10 +358,11 @@ sf_FSINCOS(uint32_t fetchdat) static int sf_FSCALE(uint32_t fetchdat) { - floatx80 result; - struct float_status_t status; + floatx80 result; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(1)) { @@ -357,8 +370,8 @@ sf_FSCALE(uint32_t fetchdat) goto next_ins; } status = i387cw_to_softfloat_status_word(i387_get_control_word()); - result = floatx80_scale(FPU_read_regi(0), FPU_read_regi(1), &status); - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + result = extF80_scale(FPU_read_regi(0), FPU_read_regi(1), &status); + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(result, 0); next_ins: @@ -371,10 +384,11 @@ sf_FSCALE(uint32_t fetchdat) static int sf_FSIN(uint32_t fetchdat) { - floatx80 y; - struct float_status_t status; + floatx80 y; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -385,10 +399,10 @@ sf_FSIN(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (fsin(&y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(y, 0); next_ins: @@ -400,10 +414,11 @@ sf_FSIN(uint32_t fetchdat) static int sf_FCOS(uint32_t fetchdat) { - floatx80 y; - struct float_status_t status; + floatx80 y; + struct softfloat_status_t status; FP_ENTER(); + FPU_check_pending_exceptions(); cpu_state.pc++; clear_C1(); clear_C2(); @@ -414,10 +429,10 @@ sf_FCOS(uint32_t fetchdat) status = i387cw_to_softfloat_status_word(i387_get_control_word() | FPU_PR_80_BITS); y = FPU_read_regi(0); if (fcos(&y, &status) == -1) { - fpu_state.swd |= C2; + fpu_state.swd |= FPU_SW_C2; goto next_ins; } - if (!FPU_exception(fetchdat, status.float_exception_flags, 0)) + if (!FPU_exception(fetchdat, status.softfloat_exceptionFlags, 0)) FPU_save_regi(y, 0); next_ins: diff --git a/src/cpu/x87_sf.h b/src/cpu/x87_sf.h new file mode 100644 index 0000000000..0388442bd4 --- /dev/null +++ b/src/cpu/x87_sf.h @@ -0,0 +1,40 @@ +/* + * 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. + * + * CPU type handler. + * + * + * + * Authors: Miran Grca, + * + * Copyright 2016-2024 Miran Grca. + */ +#ifndef EMU_X87_SF_H +#define EMU_X87_SF_H + +#include "softfloat3e/softfloat.h" + +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; + +extern fpu_state_t fpu_state; + +#endif /*EMU_X87_SF_H*/ diff --git a/src/device.c b/src/device.c index 8517045e23..41f4b74d5b 100644 --- a/src/device.c +++ b/src/device.c @@ -97,14 +97,12 @@ device_set_context(device_context_t *c, const device_t *dev, int inst) if (inst) { sprintf(c->name, "%s #%i", dev->name, inst); - /* If this is the first instance and a numbered section is not present, but a non-numbered - section of the same name is, rename the non-numbered section to numbered. */ - if (inst == 1) { - const void *sec = config_find_section(c->name); - void * single_sec = config_find_section((char *) dev->name); - if ((sec == NULL) && (single_sec != NULL)) - config_rename_section(single_sec, c->name); - } + /* If a numbered section is not present, but a non-numbered of the same name + is, rename the non-numbered section to numbered. */ + const void *sec = config_find_section(c->name); + void * single_sec = config_find_section((char *) dev->name); + if ((sec == NULL) && (single_sec != NULL)) + config_rename_section(single_sec, c->name); } else sprintf(c->name, "%s", dev->name); } @@ -186,7 +184,8 @@ device_add_common(const device_t *dev, void *p, void *params, int inst) devices[c] = NULL; device_priv[c] = NULL; - free(init_dev); + if ((init_dev != NULL) && (init_dev != (device_t *) dev)) + free(init_dev); return (NULL); } @@ -536,7 +535,7 @@ device_get_name(const device_t *dev, int bus, char *name) strcat(name, tname + strlen(sbus) + 1); /* Special case to not strip the "oPCI" from "Ensoniq AudioPCI" or the "-ISA" from "AMD PCnet-ISA". */ - else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-')) + else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-') || (*(fbus - 2) == 'r')) strcat(name, tname); else { strncat(name, tname, fbus - tname - 1); @@ -842,3 +841,31 @@ device_context_get_device(void) { return device_current.dev; } + +const device_t device_none = { + .name = "None", + .internal_name = "none", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t device_internal = { + .name = "Internal", + .internal_name = "internal", + .flags = 0, + .local = 0, + .init = NULL, + .close = NULL, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 9e3b47def9..ae3fbf3f23 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -9,21 +9,53 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. # Copyright 2021 Andreas J. Reichel. -# Copyright 2021-2022 Jasmine Iwanek. +# Copyright 2021-2024 Jasmine Iwanek. # -add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c hwm_lm78.c hwm_gl518sm.c - hwm_vt82c686.c ibm_5161.c isamem.c isartc.c ../lpt.c pci_bridge.c - postcard.c serial.c unittester.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c - smbus_piix4.c smbus_ali7101.c smbus_sis5595.c keyboard.c keyboard_xt.c - kbc_at.c kbc_at_dev.c +add_library(dev OBJECT + bugger.c + cassette.c + cartridge.c + hasp.c + hwm.c + hwm_lm75.c + hwm_lm78.c + hwm_gl518sm.c + hwm_vt82c686.c + ibm_5161.c + isamem.c + isartc.c + ../lpt.c + pci_bridge.c + postcard.c + serial.c + unittester.c + clock_ics9xxx.c + isapnp.c + i2c.c + i2c_gpio.c + smbus_piix4.c + smbus_ali7101.c + smbus_sis5595.c + keyboard.c + keyboard_xt.c + kbc_at.c + kbc_at_dev.c keyboard_at.c - mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c nec_mate_unk.c phoenix_486_jumper.c + mouse.c + mouse_bus.c + mouse_serial.c + mouse_ps2.c + nec_mate_unk.c + phoenix_486_jumper.c serial_passthrough.c - novell_cardkey.c mouse_wacom_tablet.c) + novell_cardkey.c + mouse_microtouch_touchscreen.c +) if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_link_libraries(86Box atomic) @@ -44,3 +76,12 @@ endif() if(LASERXT) target_compile_definitions(dev PRIVATE USE_LASERXT) endif() + +if(PCL) + target_compile_definitions(dev PRIVATE USE_PCL) +endif() + +if(WACOM) + target_compile_definitions(dev PRIVATE USE_WACOM) + target_sources(dev PRIVATE mouse_wacom_tablet.c) +endif() diff --git a/src/device/cartridge.c b/src/device/cartridge.c index edabd3ed0e..52f36a4caf 100644 --- a/src/device/cartridge.c +++ b/src/device/cartridge.c @@ -35,6 +35,7 @@ typedef struct cart_t { } cart_t; char cart_fns[2][512]; +char *cart_image_history[2][CART_IMAGE_HISTORY]; static cart_t carts[2]; @@ -169,6 +170,7 @@ cart_close(int drive) cart_image_close(drive); cart_fns[drive][0] = 0; ui_sb_update_icon_state(SB_CARTRIDGE | drive, 1); + resetx86(); } void diff --git a/src/device/cassette.c b/src/device/cassette.c index 1d0b885314..a239c63938 100644 --- a/src/device/cassette.c +++ b/src/device/cassette.c @@ -45,6 +45,7 @@ pc_cassette_t *cassette; char cassette_fname[512]; char cassette_mode[512]; +char * cassette_image_history[CASSETTE_IMAGE_HISTORY]; unsigned long cassette_pos; unsigned long cassette_srate; int cassette_enable; diff --git a/src/device/isamem.c b/src/device/isamem.c index 70f51ce8d4..f2332a5ccb 100644 --- a/src/device/isamem.c +++ b/src/device/isamem.c @@ -33,8 +33,10 @@ * * * Authors: Fred N. van Kempen, + * Jasmine Iwanek * - * Copyright 2018 Fred N. van Kempen. + * Copyright 2018 Fred N. van Kempen. + * Copyright 2022-2024 Jasmine Iwanek. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -88,16 +90,19 @@ #define ISAMEM_GENXT_CARD 1 #define ISAMEM_RAMCARD_CARD 2 #define ISAMEM_SYSTEMCARD_CARD 3 -#define ISAMEM_IBMAT_CARD 4 -#define ISAMEM_GENAT_CARD 5 -#define ISAMEM_P5PAK_CARD 6 -#define ISAMEM_A6PAK_CARD 7 -#define ISAMEM_EMS5150_CARD 8 +#define ISAMEM_IBMAT_128K_CARD 4 +#define ISAMEM_IBMAT_CARD 5 +#define ISAMEM_GENAT_CARD 6 +#define ISAMEM_P5PAK_CARD 7 +#define ISAMEM_A6PAK_CARD 8 +#define ISAMEM_EMS5150_CARD 9 #define ISAMEM_EV159_CARD 10 #define ISAMEM_RAMPAGEXT_CARD 11 #define ISAMEM_ABOVEBOARD_CARD 12 -#define ISAMEM_BRAT_CARD 13 -#define ISAMEM_EV165A_CARD 14 +#define ISAMEM_BRXT_CARD 13 +#define ISAMEM_BRAT_CARD 14 +#define ISAMEM_EV165A_CARD 15 +#define ISAMEM_LOTECH_CARD 16 #define ISAMEM_DEBUG 0 @@ -106,6 +111,8 @@ #define RAM_EXTMEM (1024 << 10) /* start of high memory */ #define EMS_MAXSIZE (2048 << 10) /* max EMS memory size */ +#define EMS_EV159_MAXSIZE (3072 << 10) /* max EMS memory size for EV-159 cards */ +#define EMS_LOTECH_MAXSIZE (4096 << 10) /* max EMS memory size for lotech cards */ #define EMS_PGSIZE (16 << 10) /* one page is this big */ #define EMS_MAXPAGE 4 /* number of viewport pages */ @@ -120,6 +127,11 @@ typedef struct emsreg_t { char pad; uint8_t *addr; /* start addr in EMS RAM */ mem_mapping_t mapping; /* mapping entry for page */ + uint8_t *ram; + uint8_t *frame_val; + uint16_t *ems_size; + uint16_t *ems_pages; + uint32_t *frame_addr; } emsreg_t; typedef struct ext_ram_t { @@ -132,20 +144,23 @@ typedef struct memdev_t { uint8_t board : 6; /* board type */ uint8_t reserved : 2; - uint8_t flags; + uint8_t flags; #define FLAG_CONFIG 0x01 /* card is configured */ #define FLAG_WIDE 0x10 /* card uses 16b mode */ #define FLAG_FAST 0x20 /* fast (<= 120ns) chips */ #define FLAG_EMS 0x40 /* card has EMS mode enabled */ - uint16_t total_size; /* configured size in KB */ - uint32_t base_addr; /* configured I/O address */ - uint32_t start_addr; /* configured memory start */ - uint32_t frame_addr; /* configured frame address */ + uint8_t frame_val[2]; - uint16_t ems_size; /* EMS size in KB */ - uint16_t ems_pages; /* EMS size in pages */ - uint32_t ems_start; /* start of EMS in RAM */ + uint16_t total_size; /* configured size in KB */ + uint16_t base_addr[2]; /* configured I/O address */ + + uint32_t start_addr; /* configured memory start */ + uint32_t frame_addr[2]; /* configured frame address */ + + uint16_t ems_size[2]; /* EMS size in KB */ + uint16_t ems_pages[2]; /* EMS size in pages */ + uint32_t ems_start[2]; /* start of EMS in RAM */ uint8_t *ram; /* allocated RAM buffer */ @@ -154,7 +169,7 @@ typedef struct memdev_t { mem_mapping_t low_mapping; /* mapping for low mem */ mem_mapping_t high_mapping; /* mapping for high mem */ - emsreg_t ems[EMS_MAXPAGE]; /* EMS controller registers */ + emsreg_t ems[EMS_MAXPAGE * 2]; /* EMS controller registers */ } memdev_t; #ifdef ENABLE_ISAMEM_LOG @@ -227,14 +242,14 @@ ram_writew(uint32_t addr, uint16_t val, void *priv) static uint8_t ems_readb(uint32_t addr, void *priv) { - memdev_t *dev = (memdev_t *) priv; + emsreg_t *dev = (emsreg_t *) priv; uint8_t ret = 0xff; /* Grab the data. */ - ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); + ret = *(uint8_t *) (dev->addr + (addr & 0x3fff)); #if ISAMEM_DEBUG if ((addr % 4096) == 0) - isamem_log("EMS readb(%06x) = %02x\n", addr - dev & 0x3fff, ret); + isamem_log("EMS readb(%06x) = %02x\n", addr & 0x3fff, ret); #endif return ret; @@ -244,14 +259,14 @@ ems_readb(uint32_t addr, void *priv) static uint16_t ems_readw(uint32_t addr, void *priv) { - memdev_t *dev = (memdev_t *) priv; + emsreg_t *dev = (emsreg_t *) priv; uint16_t ret = 0xffff; /* Grab the data. */ - ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)); + ret = *(uint16_t *) (dev->addr + (addr & 0x3fff)); #if ISAMEM_DEBUG if ((addr % 4096) == 0) - isamem_log("EMS readw(%06x) = %04x\n", addr - dev & 0x3fff, ret); + isamem_log("EMS readw(%06x) = %04x\n", addr & 0x3fff, ret); #endif return ret; @@ -261,46 +276,50 @@ ems_readw(uint32_t addr, void *priv) static void ems_writeb(uint32_t addr, uint8_t val, void *priv) { - memdev_t *dev = (memdev_t *) priv; + emsreg_t *dev = (emsreg_t *) priv; /* Write the data. */ #if ISAMEM_DEBUG if ((addr % 4096) == 0) - isamem_log("EMS writeb(%06x, %02x)\n", addr - dev & 0x3fff, val); + isamem_log("EMS writeb(%06x, %02x)\n", addr & 0x3fff, val); #endif - *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; + *(uint8_t *) (dev->addr + (addr & 0x3fff)) = val; } /* Write one word to onboard paged RAM. */ static void ems_writew(uint32_t addr, uint16_t val, void *priv) { - memdev_t *dev = (memdev_t *) priv; + emsreg_t *dev = (emsreg_t *) priv; /* Write the data. */ #if ISAMEM_DEBUG if ((addr % 4096) == 0) isamem_log("EMS writew(%06x, %04x)\n", addr & 0x3fff, val); #endif - *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val; + *(uint16_t *) (dev->addr + (addr & 0x3fff)) = val; } /* Handle a READ operation from one of our registers. */ static uint8_t -ems_read(uint16_t port, void *priv) +ems_in(uint16_t port, void *priv) { - const memdev_t *dev = (memdev_t *) priv; - uint8_t ret = 0xff; + const emsreg_t *dev = (emsreg_t *) priv; + uint8_t ret = 0xff; +#ifdef ENABLE_ISAMEM_LOG int vpage; +#endif /* Get the viewport page number. */ +#ifdef ENABLE_ISAMEM_LOG vpage = (port / EMS_PGSIZE); +#endif port &= (EMS_PGSIZE - 1); - switch (port - dev->base_addr) { + switch (port & 0x0001) { case 0x0000: /* page number register */ - ret = dev->ems[vpage].page; - if (dev->ems[vpage].enabled) + ret = dev->page; + if (dev->enabled) ret |= 0x80; break; @@ -311,88 +330,145 @@ ems_read(uint16_t port, void *priv) break; } -#if ISAMEM_DEBUG - isamem_log("ISAMEM: read(%04x) = %02x)\n", port, ret); -#endif + isamem_log("ISAMEM: read(%04x) = %02x) page=%d\n", port, ret, vpage); + + return ret; +} + +/* Handle a READ operation from one of our registers. */ +static uint8_t +consecutive_ems_in(uint16_t port, void *priv) +{ + const memdev_t *dev = (memdev_t *) priv; + uint8_t ret = 0xff; + int vpage; + + /* Get the viewport page number. */ + vpage = (port - dev->base_addr[0]); + + ret = dev->ems[vpage].page; + if (dev->ems[vpage].enabled) + ret |= 0x80; + + isamem_log("ISAMEM: read(%04x) = %02x) page=%d\n", port, ret, vpage); return ret; } /* Handle a WRITE operation to one of our registers. */ static void -ems_write(uint16_t port, uint8_t val, void *priv) +ems_out(uint16_t port, uint8_t val, void *priv) { - memdev_t *dev = (memdev_t *) priv; + emsreg_t *dev = (emsreg_t *) priv; int vpage; /* Get the viewport page number. */ vpage = (port / EMS_PGSIZE); port &= (EMS_PGSIZE - 1); -#if ISAMEM_DEBUG - isamem_log("ISAMEM: write(%04x, %02x) page=%d\n", port, val, vpage); -#endif - - switch (port - dev->base_addr) { + switch (port & 0x0001) { case 0x0000: /* page mapping registers */ /* Set the page number. */ - dev->ems[vpage].enabled = (val & 0x80); - dev->ems[vpage].page = (val & 0x7f); - - /* Make sure we can do that.. */ - if (dev->flags & FLAG_CONFIG) { - if (dev->ems[vpage].page < dev->ems_pages) { - /* Pre-calculate the page address in EMS RAM. */ - dev->ems[vpage].addr = dev->ram + dev->ems_start + ((val & 0x7f) * EMS_PGSIZE); - } else { - /* That page does not exist. */ - dev->ems[vpage].enabled = 0; - } - - if (dev->ems[vpage].enabled) { - /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&dev->ems[vpage].mapping, - dev->ems[vpage].addr); - - /* Enable this page. */ - mem_mapping_enable(&dev->ems[vpage].mapping); - } else { - /* Disable this page. */ - mem_mapping_disable(&dev->ems[vpage].mapping); - } + dev->enabled = (val & 0x80); + dev->page = (val & 0x7f); + + if (dev->enabled && (dev->page < *dev->ems_pages)) { + /* Pre-calculate the page address in EMS RAM. */ + dev->addr = dev->ram + ((val & 0x7f) * EMS_PGSIZE); + + isamem_log("ISAMEM: map port %04X, page %i, starting at %08X: %08X -> %08X\n", port, + vpage, *dev->frame_addr, + *dev->frame_addr + (EMS_PGSIZE * (vpage & 3)), dev->addr - dev->ram); + mem_mapping_set_addr(&dev->mapping, *dev->frame_addr + (EMS_PGSIZE * vpage), EMS_PGSIZE); + + /* Update the EMS RAM address for this page. */ + mem_mapping_set_exec(&dev->mapping, dev->addr); + + /* Enable this page. */ + mem_mapping_enable(&dev->mapping); + } else { + isamem_log("ISAMEM: map port %04X, page %i, starting at %08X: %08X -> N/A\n", + port, vpage, *dev->frame_addr, *dev->frame_addr + (EMS_PGSIZE * vpage)); + + /* Disable this page. */ + mem_mapping_disable(&dev->mapping); } break; case 0x0001: /* page frame registers */ - /* - * The EV-159 EMM driver configures the frame address - * by setting bits in these registers. The information - * in their manual is unclear, but here is what was - * found out by repeatedly changing EMM's config: - * - * 00 04 08 Address - * ----------------- - * 80 c0 e0 C0000 - * 80 c0 e0 C4000 - * 80 c0 e0 C8000 - * 80 c0 e0 CC000 - * 80 c0 e0 D0000 - * 80 c0 e0 D4000 - * 80 c0 e0 D8000 - * 80 c0 e0 DC000 - * 80 c0 e0 E0000 - */ - isamem_log("EMS: write(%02x) to register 1 !\n"); - dev->ems[vpage].frame = val; - if (val) - dev->flags |= FLAG_CONFIG; + /* + * The EV-159 EMM driver configures the frame address + * by setting bits in these registers. The information + * in their manual is unclear, but here is what was + * found out by repeatedly changing EMM's config: + * + * 08 04 00 Address + * ----------------- + * 00 00 00 C4000 + * 00 00 80 C8000 + * 00 80 00 CC000 + * 00 80 80 D0000 + * 80 00 00 D4000 + * 80 00 80 D8000 + * 80 80 00 DC000 + * 80 80 80 E0000 + */ + dev->frame = val; + *dev->frame_val = (*dev->frame_val & ~(1 << vpage)) | ((val >> 7) << vpage); + *dev->frame_addr = 0x000c4000 + (*dev->frame_val << 14); + isamem_log("ISAMEM: map port %04X page %i: frame_addr = %08X\n", port, vpage, *dev->frame_addr); + /* Destroy the page registers. */ + for (uint8_t i = 0; i < 4; i ++) { + isamem_log(" "); + outb((port & 0x3ffe) + (i << 14), 0x00); + } break; - + default: break; } } +/* Handle a WRITE operation to one of our registers. */ +static void +consecutive_ems_out(uint16_t port, uint8_t val, void *priv) +{ + memdev_t *dev = (memdev_t *) priv; + int vpage; + + /* Get the viewport page number. */ + vpage = (port - dev->base_addr[0]); + + isamem_log("ISAMEM: write(%04x, %02x) to page mapping registers! (page=%d)\n", port, val, vpage); + + /* Set the page number. */ + dev->ems[vpage].enabled = 1; + dev->ems[vpage].page = val; + + /* Make sure we can do that.. */ + if (dev->flags & FLAG_CONFIG) { + if (dev->ems[vpage].page < dev->ems_pages[0]) { + /* Pre-calculate the page address in EMS RAM. */ + dev->ems[vpage].addr = dev->ram + dev->ems_start[0] + (val * EMS_PGSIZE); + } else { + /* That page does not exist. */ + dev->ems[vpage].enabled = 0; + } + + if (dev->ems[vpage].enabled) { + /* Update the EMS RAM address for this page. */ + mem_mapping_set_exec(&dev->ems[vpage].mapping, + dev->ems[vpage].addr); + + /* Enable this page. */ + mem_mapping_enable(&dev->ems[vpage].mapping); + } else { + /* Disable this page. */ + mem_mapping_disable(&dev->ems[vpage].mapping); + } + } +} + /* Initialize the device for use. */ static void * isamem_init(const device_t *info) @@ -402,6 +478,8 @@ isamem_init(const device_t *info) uint32_t t; uint32_t addr; uint32_t tot; + /* EMS 3.2 cannot have more than 2048KB per board. */ + uint32_t ems_max = EMS_MAXSIZE; uint8_t *ptr; /* Find our device and create an instance. */ @@ -410,6 +488,9 @@ isamem_init(const device_t *info) dev->name = info->name; dev->board = info->local; + dev->base_addr[1] = 0x0000; + dev->frame_addr[1] = 0x00000000; + /* Do per-board initialization. */ tot = 0; switch (dev->board) { @@ -424,6 +505,13 @@ isamem_init(const device_t *info) tot = dev->total_size; break; + case ISAMEM_IBMAT_128K_CARD: /* IBM PC/AT 128K Memory Expansion Option */ + dev->total_size = 128; + dev->start_addr = 512; + tot = dev->total_size; + dev->flags |= FLAG_WIDE; + break; + case ISAMEM_IBMAT_CARD: /* IBM PC/AT Memory Expansion Card */ case ISAMEM_GENAT_CARD: /* Generic PC/AT Memory Expansion Card */ dev->total_size = device_get_config_int("size"); @@ -433,47 +521,74 @@ isamem_init(const device_t *info) break; case ISAMEM_EMS5150_CARD: /* Micro Mainframe EMS-5150(T) */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->frame_addr = 0xD0000; - dev->flags |= (FLAG_EMS | FLAG_CONFIG); + dev->base_addr[0] = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = 0; + dev->frame_addr[0] = 0xd0000; + dev->flags |= (FLAG_EMS | FLAG_CONFIG); break; case ISAMEM_EV159_CARD: /* Everex EV-159 RAM 3000 */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = device_get_config_int("length"); + /* The EV-159 cannot have more than 3072KB per board. */ + ems_max = EMS_EV159_MAXSIZE; + dev->base_addr[0] = device_get_config_hex16("base"); + dev->base_addr[1] = device_get_config_hex16("base2"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = device_get_config_int("length"); if (!!device_get_config_int("width")) - dev->flags |= FLAG_WIDE; + dev->flags |= FLAG_WIDE; if (!!device_get_config_int("speed")) - dev->flags |= FLAG_FAST; + dev->flags |= FLAG_FAST; if (!!device_get_config_int("ems")) - dev->flags |= FLAG_EMS; - dev->frame_addr = 0xE0000; + dev->flags |= FLAG_EMS; + dev->frame_addr[0] = 0xd0000; + dev->frame_addr[1] = 0xe0000; break; case ISAMEM_EV165A_CARD: /* Everex Maxi Magic EV-165A */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = device_get_config_int("length"); + dev->base_addr[0] = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = device_get_config_int("length"); if (!!device_get_config_int("ems")) - dev->flags |= FLAG_EMS; - dev->frame_addr = 0xE0000; + dev->flags |= FLAG_EMS; + dev->frame_addr[0] = 0xe0000; break; case ISAMEM_RAMPAGEXT_CARD: /* AST RAMpage/XT */ + dev->base_addr[0] = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = device_get_config_int("start"); + tot = dev->total_size; + dev->flags |= FLAG_EMS; + dev->frame_addr[0] = 0xe0000; + break; + case ISAMEM_ABOVEBOARD_CARD: /* Intel AboveBoard */ case ISAMEM_BRAT_CARD: /* BocaRAM/AT */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - dev->frame_addr = device_get_config_hex20("frame"); + dev->base_addr[0] = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + if (!!device_get_config_int("start")) + dev->start_addr = device_get_config_int("start"); + dev->frame_addr[0] = device_get_config_hex20("frame"); + dev->flags |= FLAG_EMS; if (!!device_get_config_int("width")) - dev->flags |= FLAG_WIDE; + dev->flags |= FLAG_WIDE; if (!!device_get_config_int("speed")) - dev->flags |= FLAG_FAST; + dev->flags |= FLAG_FAST; + break; + + case ISAMEM_LOTECH_CARD: /* Lotech EMS */ + /* The Lotech EMS cannot have more than 4096KB per board. */ + ems_max = EMS_LOTECH_MAXSIZE; + fallthrough; + case ISAMEM_BRXT_CARD: /* BocaRAM/XT */ + dev->base_addr[0] = device_get_config_hex16("base"); + dev->total_size = device_get_config_int("size"); + dev->start_addr = 0; + dev->frame_addr[0] = device_get_config_hex20("frame"); + dev->flags |= (FLAG_EMS | FLAG_CONFIG); break; default: @@ -625,31 +740,54 @@ isamem_init(const device_t *info) /* If EMS is enabled, use the remainder for EMS. */ if (dev->flags & FLAG_EMS) { - /* EMS 3.2 cannot have more than 2048KB per board. */ t = k; - if (t > EMS_MAXSIZE) - t = EMS_MAXSIZE; + + if (t > ems_max) + t = ems_max; /* Set up where EMS begins in local RAM, and how much we have. */ - dev->ems_start = ptr - dev->ram; - dev->ems_size = t >> 10; - dev->ems_pages = t / EMS_PGSIZE; - isamem_log("ISAMEM: EMS enabled, I/O=%04XH, %iKB (%i pages)", - dev->base_addr, dev->ems_size, dev->ems_pages); - if (dev->frame_addr > 0) - isamem_log(", Frame=%05XH", dev->frame_addr); + dev->ems_start[0] = ptr - dev->ram; + if ((dev->board == ISAMEM_EV159_CARD) && (t > (2 << 20))) { + dev->ems_size[0] = 2 << 10; + dev->ems_pages[0] = (2 << 20) / EMS_PGSIZE; + } else { + dev->ems_size[0] = t >> 10; + dev->ems_pages[0] = t / EMS_PGSIZE; + } + isamem_log("ISAMEM: EMS #1 enabled, I/O=%04XH, %iKB (%i pages)", + dev->base_addr[0], dev->ems_size[0], dev->ems_pages[0]); + if (dev->frame_addr[0] > 0) + isamem_log(", Frame[0]=%05XH", dev->frame_addr[0]); isamem_log("\n"); + if ((dev->board == ISAMEM_EV159_CARD) && (t > (2 << 20))) { + dev->ems_start[1] = dev->ems_start[0] + (2 << 20); + dev->ems_size[1] = (t - (2 << 20)) >> 10; + dev->ems_pages[1] = (t - (2 << 20)) / EMS_PGSIZE; + isamem_log("ISAMEM: EMS #2 enabled, I/O=%04XH, %iKB (%i pages)", + dev->base_addr[1], dev->ems_size[1], dev->ems_pages[1]); + if (dev->frame_addr[1] > 0) + isamem_log(", Frame[1]=%05XH", dev->frame_addr[1]); + + isamem_log("\n"); + } + /* * For each supported page (we can have a maximum of 4), * create, initialize and disable the mappings, and set * up the I/O control handler. */ for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { + dev->ems[i].ram = dev->ram + dev->ems_start[0]; + dev->ems[i].frame_val = &dev->frame_val[0]; + dev->ems[i].ems_size = &dev->ems_size[0]; + dev->ems[i].ems_pages = &dev->ems_pages[0]; + dev->ems[i].frame_addr = &dev->frame_addr[0]; + /* Create and initialize a page mapping. */ mem_mapping_add(&dev->ems[i].mapping, - dev->frame_addr + (EMS_PGSIZE * i), EMS_PGSIZE, + dev->frame_addr[0] + (EMS_PGSIZE * i), EMS_PGSIZE, ems_readb, (dev->flags & FLAG_WIDE) ? ems_readw : NULL, NULL, @@ -657,15 +795,46 @@ isamem_init(const device_t *info) (dev->flags & FLAG_WIDE) ? ems_writew : NULL, NULL, ptr, MEM_MAPPING_EXTERNAL, - dev); + &(dev->ems[i])); /* For now, disable it. */ mem_mapping_disable(&dev->ems[i].mapping); /* Set up an I/O port handler. */ - io_sethandler(dev->base_addr + (EMS_PGSIZE * i), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); + if (dev->board != ISAMEM_LOTECH_CARD) + io_sethandler(dev->base_addr[0] + (EMS_PGSIZE * i), 2, + ems_in, NULL, NULL, ems_out, NULL, NULL, &(dev->ems[i])); + + if ((dev->board == ISAMEM_EV159_CARD) && (t > (2 << 20))) { + dev->ems[i | 4].ram = dev->ram + dev->ems_start[1]; + dev->ems[i | 4].frame_val = &dev->frame_val[1]; + dev->ems[i | 4].ems_size = &dev->ems_size[1]; + dev->ems[i | 4].ems_pages = &dev->ems_pages[1]; + dev->ems[i | 4].frame_addr = &dev->frame_addr[1]; + + /* Create and initialize a page mapping. */ + mem_mapping_add(&dev->ems[i | 4].mapping, + dev->frame_addr[1] + (EMS_PGSIZE * i), EMS_PGSIZE, + ems_readb, + (dev->flags & FLAG_WIDE) ? ems_readw : NULL, + NULL, + ems_writeb, + (dev->flags & FLAG_WIDE) ? ems_writew : NULL, + NULL, + ptr + (2 << 20), MEM_MAPPING_EXTERNAL, + &(dev->ems[i | 4])); + + /* For now, disable it. */ + mem_mapping_disable(&dev->ems[i | 4].mapping); + + io_sethandler(dev->base_addr[1] + (EMS_PGSIZE * i), 2, + ems_in, NULL, NULL, ems_out, NULL, NULL, &(dev->ems[i | 4])); + } } + + if (dev->board == ISAMEM_LOTECH_CARD) + io_sethandler(dev->base_addr[0], 4, + consecutive_ems_in, NULL, NULL, consecutive_ems_out, NULL, NULL, dev); } /* Let them know our device instance. */ @@ -678,19 +847,108 @@ isamem_close(void *priv) { memdev_t *dev = (memdev_t *) priv; - if (dev->flags & FLAG_EMS) { - for (uint8_t i = 0; i < EMS_MAXPAGE; i++) { - io_removehandler(dev->base_addr + (EMS_PGSIZE * i), 2, - ems_read, NULL, NULL, ems_write, NULL, NULL, dev); - } - } - if (dev->ram != NULL) free(dev->ram); free(dev); } +static const device_config_t ibmxt_32k_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 32, + .file_filter = "", + .spinner = { + .min = 32, + .max = 576, + .step = 32 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 64, + .file_filter = "", + .spinner = { + .min = 0, + .max = 608, + .step = 32 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_t ibmxt_32k_device = { + .name = "IBM PC/XT 32K Memory Expansion Option", + .internal_name = "ibmxt_32k", + .flags = DEVICE_ISA, + .local = ISAMEM_IBMXT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt_32k_config +}; + +static const device_config_t ibmxt_64k_config[] = { + // clang-format off + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 64, + .file_filter = "", + .spinner = { + .min = 64, + .max = 576, + .step = 64 + }, + .selection = { { 0 } } + }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 64, + .file_filter = "", + .spinner = { + .min = 0, + .max = 576, + .step = 64 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_t ibmxt_64k_device = { + .name = "IBM PC/XT 64K Memory Expansion Option", + .internal_name = "ibmxt_64k", + .flags = DEVICE_ISA, + .local = ISAMEM_IBMXT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ibmxt_64k_config +}; + static const device_config_t ibmxt_config[] = { // clang-format off { @@ -701,9 +959,9 @@ static const device_config_t ibmxt_config[] = { .default_int = 128, .file_filter = "", .spinner = { - .min = 0, - .max = 512, - .step = 16 + .min = 64, + .max = 576, + .step = 64 }, .selection = { { 0 } } }, @@ -726,7 +984,7 @@ static const device_config_t ibmxt_config[] = { }; static const device_t ibmxt_device = { - .name = "IBM PC/XT Memory Expansion", + .name = "IBM PC/XT 64/256K Memory Expansion Option", .internal_name = "ibmxt", .flags = DEVICE_ISA, .local = ISAMEM_IBMXT_CARD, @@ -883,6 +1141,20 @@ static const device_t mssystemcard_device = { .config = mssystemcard_config }; +static const device_t ibmat_128k_device = { + .name = "IBM PC/AT 128KB Memory Expansion Option", + .internal_name = "ibmat_128k", + .flags = DEVICE_ISA, + .local = ISAMEM_IBMAT_128K_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + static const device_config_t ibmat_config[] = { // clang-format off { @@ -904,7 +1176,7 @@ static const device_config_t ibmat_config[] = { .description = "Start Address", .type = CONFIG_SPINNER, .default_string = "", - .default_int = 512, + .default_int = 1024, .file_filter = "", .spinner = { .min = 0, @@ -943,7 +1215,7 @@ static const device_config_t genericat_config[] = { .spinner = { .min = 0, .max = 16384, - .step = 512 + .step = 128 }, .selection = { { 0 } } }, @@ -952,7 +1224,7 @@ static const device_config_t genericat_config[] = { .description = "Start Address", .type = CONFIG_SPINNER, .default_string = "", - .default_int = 512, + .default_int = 1024, .file_filter = "", .spinner = { .min = 0, @@ -1231,6 +1503,25 @@ static const device_config_t ev159_config[] = { { .description = "" } }, }, + { + .name = "base2", + .description = "Address for > 2 MB", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0268, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "2A8H", .value = 0x02A8 }, + { .description = "2B8H", .value = 0x02B8 }, + { .description = "2E8H", .value = 0x02E8 }, + { .description = "" } + }, + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1344,7 +1635,71 @@ static const device_t ev165a_device = { .config = ev165a_config }; -#if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT) +static const device_config_t brxt_config[] = { + // clang-format off + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x0268, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "" } + }, + }, + { + .name = "frame", + .description = "Frame Address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xD0000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "D000H", .value = 0xD0000 }, + { .description = "E000H", .value = 0xE0000 }, + { .description = "" } + }, + }, + { + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 512, + .file_filter = "", + .spinner = { + .min = 0, + .max = 2048, + .step = 512 + }, + .selection = { { 0 } } + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_t brxt_device = { + .name = "BocaRAM/XT", + .internal_name = "brxt", + .flags = DEVICE_ISA, + .local = ISAMEM_BRXT_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = brxt_config +}; + +#ifdef USE_ISAMEM_BRAT static const device_config_t brat_config[] = { // clang-format off { @@ -1352,7 +1707,7 @@ static const device_config_t brat_config[] = { .description = "Address", .type = CONFIG_HEX16, .default_string = "", - .default_int = 0x0258, + .default_int = 0x0268, .file_filter = "", .spinner = { 0 }, .selection = { @@ -1368,11 +1723,10 @@ static const device_config_t brat_config[] = { .description = "Frame Address", .type = CONFIG_HEX20, .default_string = "", - .default_int = 0, + .default_int = 0xD0000, .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "Disabled", .value = 0x00000 }, { .description = "D000H", .value = 0xD0000 }, { .description = "E000H", .value = 0xE0000 }, { .description = "" } @@ -1411,15 +1765,28 @@ static const device_config_t brat_config[] = { .description = "Memory Size", .type = CONFIG_SPINNER, .default_string = "", - .default_int = 128, + .default_int = 512, .file_filter = "", .spinner = { .min = 0, - .max = 8192, + .max = 4096, .step = 512 }, .selection = { { 0 } } }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { + .min = 0, + .max = 14336, + .step = 512 + }, + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1437,27 +1804,23 @@ static const device_t brat_device = { .force_redraw = NULL, .config = brat_config }; -#endif +#endif /* USE_ISAMEM_BRAT */ -#if defined(DEV_BRANCH) && defined(USE_ISAMEM_RAMPAGE) -static const device_config_t rampage_config[] = { - // clang-format off +static const device_config_t lotech_config[] = { +// clang-format off { .name = "base", .description = "Address", .type = CONFIG_HEX16, .default_string = "", - .default_int = 0x0258, + .default_int = 0x0260, .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "208H", .value = 0x0208 }, - { .description = "218H", .value = 0x0218 }, - { .description = "258H", .value = 0x0258 }, + { .description = "260H", .value = 0x0260 }, + { .description = "264H", .value = 0x0264 }, { .description = "268H", .value = 0x0268 }, - { .description = "2A8H", .value = 0x02A8 }, - { .description = "2B8H", .value = 0x02B8 }, - { .description = "2E8H", .value = 0x02E8 }, + { .description = "26CH", .value = 0x026C }, { .description = "" } }, }, @@ -1466,11 +1829,10 @@ static const device_config_t rampage_config[] = { .description = "Frame Address", .type = CONFIG_HEX20, .default_string = "", - .default_int = 0, + .default_int = 0xe0000, .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "Disabled", .value = 0x00000 }, { .description = "C000H", .value = 0xC0000 }, { .description = "D000H", .value = 0xD0000 }, { .description = "E000H", .value = 0xE0000 }, @@ -1478,47 +1840,88 @@ static const device_config_t rampage_config[] = { }, }, { - .name = "width", - .description = "I/O Width", - .type = CONFIG_SELECTION, + .name = "size", + .description = "Memory Size", + .type = CONFIG_SPINNER, .default_string = "", - .default_int = 8, + .default_int = 2048, .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "8-bit", .value = 8 }, - { .description = "16-bit", .value = 16 }, - { .description = "" } + .spinner = { + .min = 512, + .max = 4096, + .step = 512 }, + .selection = { { 0 } } }, + { .name = "", .description = "", .type = CONFIG_END } +// clang-format on +}; + +static const device_t lotech_device = { + .name = "Lo-tech EMS Board", + .internal_name = "lotechems", + .flags = DEVICE_ISA, + .local = ISAMEM_LOTECH_CARD, + .init = isamem_init, + .close = isamem_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = lotech_config +}; + +#ifdef USE_ISAMEM_RAMPAGE +// TODO: Dual Paging support +// TODO: Conventional memory suppport +static const device_config_t rampage_config[] = { + // clang-format off { - .name = "speed", - .description = "Transfer Speed", - .type = CONFIG_SELECTION, + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, .default_string = "", - .default_int = 0, + .default_int = 0x0218, .file_filter = "", .spinner = { 0 }, .selection = { - { .description = "Standard", .value = 0 }, - { .description = "High-Speed", .value = 1 }, - { .description = "" } - } + { .description = "208H", .value = 0x0208 }, + { .description = "218H", .value = 0x0218 }, + { .description = "258H", .value = 0x0258 }, + { .description = "268H", .value = 0x0268 }, + { .description = "2A8H", .value = 0x02A8 }, + { .description = "2B8H", .value = 0x02B8 }, + { .description = "2E8H", .value = 0x02E8 }, + { .description = "" } + }, }, { .name = "size", .description = "Memory Size", .type = CONFIG_SPINNER, .default_string = "", - .default_int = 128, + .default_int = 256, /* Technically 128k, but banks 2-7 must be 256, headaches elsewise */ .file_filter = "", .spinner = { - .min = 0, - .max = 8192, - .step = 128 + .min = 256, + .max = 2048, + .step = 256 }, .selection = { { 0 } } }, + { + .name = "start", + .description = "Start Address", + .type = CONFIG_SPINNER, + .default_string = "", + .default_int = 640, + .file_filter = "", + .spinner = { + .min = 0, + .max = 640, + .step = 64 + }, + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -1536,9 +1939,9 @@ static const device_t rampage_device = { .force_redraw = NULL, .config = rampage_config }; -#endif +#endif /* USE_ISAMEM_RAMPAGE */ -#if defined(DEV_BRANCH) && defined(USE_ISAMEM_IAB) +#ifdef USE_ISAMEM_IAB static const device_config_t iab_config[] = { // clang-format off { @@ -1635,47 +2038,41 @@ static const device_t iab_device = { .force_redraw = NULL, .config = iab_config }; -#endif - -static const device_t isa_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; +#endif /* USE_ISAMEM_IAB */ static const struct { const device_t *dev; } boards[] = { // clang-format off - { &isa_none_device }, + { &device_none }, + // XT Ram Expansion Cards + { &ibmxt_32k_device }, + { &ibmxt_64k_device }, { &ibmxt_device }, { &genericxt_device }, { &msramcard_device }, { &mssystemcard_device }, + // AT RAM Expansion Cards + { &ibmat_128k_device }, { &ibmat_device }, { &genericat_device }, + // EMS Cards { &p5pak_device }, { &a6pak_device }, { &ems5150_device }, { &ev159_device }, { &ev165a_device }, -#if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT) + { &brxt_device }, +#ifdef USE_ISAMEM_BRAT { &brat_device }, -#endif -#if defined(DEV_BRANCH) && defined(USE_ISAMEM_RAMPAGE) +#endif /* USE_ISAMEM_BRAT */ +#ifdef USE_ISAMEM_RAMPAGE { &rampage_device }, -#endif -#if defined(DEV_BRANCH) && defined(USE_ISAMEM_IAB) +#endif /* USE_ISAMEM_RAMPAGE */ +#ifdef USE_ISAMEM_IAB { &iab_device }, -#endif +#endif /* USE_ISAMEM_IAB */ + { &lotech_device }, { NULL } // clang-format on }; @@ -1734,3 +2131,12 @@ isamem_get_device(int board) /* Add the instance to the system. */ return boards[board].dev; } + +int +isamem_has_config(int board) +{ + if (boards[board].dev == NULL) + return 0; + + return (boards[board].dev->config ? 1 : 0); +} diff --git a/src/device/isartc.c b/src/device/isartc.c index 46f31c1373..7721d9885e 100644 --- a/src/device/isartc.c +++ b/src/device/isartc.c @@ -752,30 +752,16 @@ const device_t vendex_xt_rtc_onboard_device = { .config = NULL }; -static const device_t isartc_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const struct { const device_t *dev; } boards[] = { // clang-format off - { &isartc_none_device }, - { &ev170_device }, - { &pii147_device }, - { &p5pak_device }, - { &a6pak_device }, - { NULL }, + { &device_none }, + { &ev170_device }, + { &pii147_device }, + { &p5pak_device }, + { &a6pak_device }, + { NULL }, // clang-format on }; @@ -815,3 +801,12 @@ isartc_get_device(int board) { return (boards[board].dev); } + +int +isartc_has_config(int board) +{ + if (boards[board].dev == NULL) + return 0; + + return (boards[board].dev->config ? 1 : 0); +} diff --git a/src/device/kbc_at.c b/src/device/kbc_at.c index dd18649de0..5c3c9ac6e0 100644 --- a/src/device/kbc_at.c +++ b/src/device/kbc_at.c @@ -277,9 +277,26 @@ kbc_translate(atkbc_t *dev, uint8_t val) return ret; } + kbc_at_log("ATkbc: translate is %s, ", translate ? "on" : "off"); +#ifdef ENABLE_KEYBOARD_AT_LOG + kbc_at_log("scan code: "); + if (translate) { + kbc_at_log("%02X (original: ", (nont_to_t[val] | dev->sc_or)); + if (dev->sc_or == 0x80) + kbc_at_log("F0 "); + kbc_at_log("%02X)\n", val); + } else + kbc_at_log("%02X\n", val); +#endif + + ret = translate ? (nont_to_t[val] | dev->sc_or) : val; + + if (dev->sc_or == 0x80) + dev->sc_or = 0; + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && - (keyboard_recv(0x138) || keyboard_recv(0x11d))) switch (val) { + (keyboard_recv(0x138) || keyboard_recv(0x11d))) switch (ret) { case 0x4f: t3100e_notify_set(0x01); break; /* End */ @@ -329,23 +346,6 @@ kbc_translate(atkbc_t *dev, uint8_t val) break; } - kbc_at_log("ATkbc: translate is %s, ", translate ? "on" : "off"); -#ifdef ENABLE_KEYBOARD_AT_LOG - kbc_at_log("scan code: "); - if (translate) { - kbc_at_log("%02X (original: ", (nont_to_t[val] | dev->sc_or)); - if (dev->sc_or == 0x80) - kbc_at_log("F0 "); - kbc_at_log("%02X)\n", val); - } else - kbc_at_log("%02X\n", val); -#endif - - ret = translate ? (nont_to_t[val] | dev->sc_or) : val; - - if (dev->sc_or == 0x80) - dev->sc_or = 0; - return ret; } @@ -422,6 +422,14 @@ kbc_delay_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) dev->stat_hi = stat_hi; dev->pending = 1; dev->state = STATE_KBC_DELAY_OUT; + + if (dev->is_asic && (channel == 0) && (dev->status & STAT_OFULL)) { + /* Expedite the sending to the output buffer to prevent the wrong + data from being accidentally read. */ + kbc_send_to_ob(dev, dev->val, dev->channel, dev->stat_hi); + dev->state = STATE_MAIN_IBF; + dev->pending = 0; + } } static void kbc_at_process_cmd(void *priv); @@ -813,14 +821,14 @@ write_p2(atkbc_t *dev, uint8_t val) softresetx86(); /* Pulse reset! */ cpu_set_edx(); flushmmucache(); - if (kbc_ven == KBC_VEN_ALI) + if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw")) smbase = 0x00030000; /* Yes, this is a hack, but until someone gets ahold of the real PCD-2L and can find out what they actually did to make it boot from FFFFF0 correctly despite A20 being gated when the CPU is reset, this will have to do. */ - if (kbc_ven == KBC_VEN_SIEMENS) + if ((kbc_ven == KBC_VEN_SIEMENS) || !strcmp(machine_get_internal_name(), "acera1g")) is486 ? loadcs(0xf000) : loadcs_2386(0xf000); } } @@ -1181,6 +1189,23 @@ write60_ami(void *priv, uint8_t val) return 1; } +void +kbc_at_set_ps2(void *priv, const uint8_t ps2) +{ + atkbc_t *dev = (atkbc_t *) priv; + + dev->ami_flags = (dev->ami_flags & 0xfe) | (!!ps2); + dev->misc_flags &= ~FLAG_PS2; + if (ps2) { + dev->misc_flags |= FLAG_PS2; + kbc_at_do_poll = kbc_at_poll_ps2; + } else + kbc_at_do_poll = kbc_at_poll_at; + + write_cmd(dev, ~dev->mem[0x20]); + write_cmd(dev, dev->mem[0x20]); +} + static uint8_t write64_ami(void *priv, uint8_t val) { @@ -2208,7 +2233,11 @@ static void kbc_at_close(void *priv) { atkbc_t *dev = (atkbc_t *) priv; +#ifdef OLD_CODE int max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1; +#else + int max_ports = 2; +#endif /* Stop timers. */ timer_disable(&dev->kbc_dev_poll_timer); @@ -2350,7 +2379,11 @@ kbc_at_init(const device_t *info) break; } +#ifdef OLD_CODE max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) ? 2 : 1; +#else + max_ports = 2; +#endif for (int i = 0; i < max_ports; i++) { kbc_at_ports[i] = (kbc_at_port_t *) malloc(sizeof(kbc_at_port_t)); diff --git a/src/device/keyboard.c b/src/device/keyboard.c index 5f9986d7bb..ea81e75257 100644 --- a/src/device/keyboard.c +++ b/src/device/keyboard.c @@ -25,6 +25,7 @@ #include <86box/86box.h> #include <86box/machine.h> #include <86box/keyboard.h> +#include <86box/plat.h> #include "cpu.h" @@ -50,7 +51,8 @@ uint16_t key_uncapture_2 = 0x14f; /* End */ void (*keyboard_send)(uint16_t val); -static int recv_key[512]; /* keyboard input buffer */ +static int recv_key[512] = { 0 }; /* keyboard input buffer */ +static int recv_key_ui[512] = { 0 }; /* keyboard input buffer */ static int oldkey[512]; #if 0 static int keydelay[512]; @@ -238,16 +240,13 @@ keyboard_input(int down, uint16_t scan) } } - /* NOTE: Shouldn't this be some sort of bit shift? An array of 8 unsigned 64-bit integers - should be enough. */ -#if 0 - recv_key[scan >> 6] |= ((uint64_t) down << ((uint64_t) scan & 0x3fLL)); -#endif - /* pclog("Received scan code: %03X (%s)\n", scan & 0x1ff, down ? "down" : "up"); */ - recv_key[scan & 0x1ff] = down; + recv_key_ui[scan & 0x1ff] = down; - key_process(scan & 0x1ff, down); + if (mouse_capture || !kbd_req_capture || video_fullscreen) { + recv_key[scan & 0x1ff] = down; + key_process(scan & 0x1ff, down); + } } static uint8_t @@ -343,30 +342,36 @@ keyboard_recv(uint16_t key) return recv_key[key]; } +int +keyboard_recv_ui(uint16_t key) +{ + return recv_key_ui[key]; +} + /* Do we have Control-Alt-PgDn in the keyboard buffer? */ int keyboard_isfsenter(void) { - return ((recv_key[0x01d] || recv_key[0x11d]) && (recv_key[0x038] || recv_key[0x138]) && (recv_key[0x049] || recv_key[0x149])); + return ((recv_key_ui[0x01d] || recv_key_ui[0x11d]) && (recv_key_ui[0x038] || recv_key_ui[0x138]) && (recv_key_ui[0x049] || recv_key_ui[0x149])); } int keyboard_isfsenter_up(void) { - return (!recv_key[0x01d] && !recv_key[0x11d] && !recv_key[0x038] && !recv_key[0x138] && !recv_key[0x049] && !recv_key[0x149]); + return (!recv_key_ui[0x01d] && !recv_key_ui[0x11d] && !recv_key_ui[0x038] && !recv_key_ui[0x138] && !recv_key_ui[0x049] && !recv_key_ui[0x149]); } /* Do we have Control-Alt-PgDn in the keyboard buffer? */ int keyboard_isfsexit(void) { - return ((recv_key[0x01d] || recv_key[0x11d]) && (recv_key[0x038] || recv_key[0x138]) && (recv_key[0x051] || recv_key[0x151])); + return ((recv_key_ui[0x01d] || recv_key_ui[0x11d]) && (recv_key_ui[0x038] || recv_key_ui[0x138]) && (recv_key_ui[0x051] || recv_key_ui[0x151])); } int keyboard_isfsexit_up(void) { - return (!recv_key[0x01d] && !recv_key[0x11d] && !recv_key[0x038] && !recv_key[0x138] && !recv_key[0x051] && !recv_key[0x151]); + return (!recv_key_ui[0x01d] && !recv_key_ui[0x11d] && !recv_key_ui[0x038] && !recv_key_ui[0x138] && !recv_key_ui[0x051] && !recv_key_ui[0x151]); } /* Do we have the mouse uncapture combination in the keyboard buffer? */ @@ -374,10 +379,10 @@ int keyboard_ismsexit(void) { if ((key_prefix_2_1 != 0x000) || (key_prefix_2_2 != 0x000)) - return ((recv_key[key_prefix_1_1] || recv_key[key_prefix_1_2]) && - (recv_key[key_prefix_2_1] || recv_key[key_prefix_2_2]) && - (recv_key[key_uncapture_1] || recv_key[key_uncapture_2])); + return ((recv_key_ui[key_prefix_1_1] || recv_key_ui[key_prefix_1_2]) && + (recv_key_ui[key_prefix_2_1] || recv_key_ui[key_prefix_2_2]) && + (recv_key_ui[key_uncapture_1] || recv_key_ui[key_uncapture_2])); else - return ((recv_key[key_prefix_1_1] || recv_key[key_prefix_1_2]) && - (recv_key[key_uncapture_1] || recv_key[key_uncapture_2])); + return ((recv_key_ui[key_prefix_1_1] || recv_key_ui[key_prefix_1_2]) && + (recv_key_ui[key_uncapture_1] || recv_key_ui[key_uncapture_2])); } diff --git a/src/device/keyboard_at.c b/src/device/keyboard_at.c index 7accb2fd6c..882174e4e4 100644 --- a/src/device/keyboard_at.c +++ b/src/device/keyboard_at.c @@ -81,397 +81,1552 @@ static uint16_t bat_counter = 0; static const scancode scancode_set1[512] = { // clang-format off - { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ - { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ - { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ - { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ - { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ - { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ - { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ - { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ - { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ - { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ - { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ - { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ - { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ - { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ - { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ - { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ - { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ - { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ - { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ - { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ - { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ - { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ - { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ - { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ - { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ - { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ - { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ - { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ - { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ - { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ - { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ - { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ - - { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ - { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ - { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ - { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ - { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ - { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ - { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ - { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ - { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ - { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ - { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ - { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ - { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ - { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ - { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ - { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ - { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ - { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ - { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ - { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ - { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ - { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ - { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ - { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ - { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ - { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ - { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ - { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ - { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ - { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ - - { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ - { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ - { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ - { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ - { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ - { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ - { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ - { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ - { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ - { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ - { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ - { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ - { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ - { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ - { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ - { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ - { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ - { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ - { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ - { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ - { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ - { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ - { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ - { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ - { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ - { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 012 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0x54, 0 }, .brk = { 0xd4, 0 } }, /* 054 */ + { .mk = { 0x55, 0 }, .brk = { 0xd5, 0 } }, /* 055 */ + { .mk = { 0x56, 0 }, .brk = { 0xd6, 0 } }, /* 056 */ + { .mk = { 0x57, 0 }, .brk = { 0xd7, 0 } }, /* 057 */ + { .mk = { 0x58, 0 }, .brk = { 0xd8, 0 } }, /* 058 */ + { .mk = { 0x59, 0 }, .brk = { 0xd9, 0 } }, /* 059 */ + { .mk = { 0x5a, 0 }, .brk = { 0xda, 0 } }, /* 05a */ + { .mk = { 0x5b, 0 }, .brk = { 0xdb, 0 } }, /* 05b */ + { .mk = { 0x5c, 0 }, .brk = { 0xdc, 0 } }, /* 05c */ + { .mk = { 0x5d, 0 }, .brk = { 0xdd, 0 } }, /* 05d */ + { .mk = { 0x5e, 0 }, .brk = { 0xde, 0 } }, /* 05e */ + { .mk = { 0x5f, 0 }, .brk = { 0xdf, 0 } }, /* 05f */ + { .mk = { 0x60, 0 }, .brk = { 0xe0, 0 } }, /* 060 */ + { .mk = { 0x61, 0 }, .brk = { 0xe1, 0 } }, /* 061 */ + { .mk = { 0x62, 0 }, .brk = { 0xe2, 0 } }, /* 062 */ + { .mk = { 0x63, 0 }, .brk = { 0xe3, 0 } }, /* 063 */ + { .mk = { 0x64, 0 }, .brk = { 0xe4, 0 } }, /* 064 */ + { .mk = { 0x65, 0 }, .brk = { 0xe5, 0 } }, /* 065 */ + { .mk = { 0x66, 0 }, .brk = { 0xe6, 0 } }, /* 066 */ + { .mk = { 0x67, 0 }, .brk = { 0xe7, 0 } }, /* 067 */ + { .mk = { 0x68, 0 }, .brk = { 0xe8, 0 } }, /* 068 */ + { .mk = { 0x69, 0 }, .brk = { 0xe9, 0 } }, /* 069 */ + { .mk = { 0x6a, 0 }, .brk = { 0xea, 0 } }, /* 06a */ + { .mk = { 0x6b, 0 }, .brk = { 0xeb, 0 } }, /* 06b */ + { .mk = { 0x6c, 0 }, .brk = { 0xec, 0 } }, /* 06c */ + { .mk = { 0x6d, 0 }, .brk = { 0xed, 0 } }, /* 06d */ + { .mk = { 0x6e, 0 }, .brk = { 0xee, 0 } }, /* 06e */ + { .mk = { 0x6f, 0 }, .brk = { 0xef, 0 } }, /* 06f */ + { .mk = { 0x70, 0 }, .brk = { 0xf0, 0 } }, /* 070 */ + { .mk = { 0x71, 0 }, .brk = { 0xf1, 0 } }, /* 071 */ + { .mk = { 0x72, 0 }, .brk = { 0xf2, 0 } }, /* 072 */ + { .mk = { 0x73, 0 }, .brk = { 0xf3, 0 } }, /* 073 */ + { .mk = { 0x74, 0 }, .brk = { 0xf4, 0 } }, /* 074 */ + { .mk = { 0x75, 0 }, .brk = { 0xf5, 0 } }, /* 075 */ + { .mk = { 0x76, 0 }, .brk = { 0xf6, 0 } }, /* 076 */ + { .mk = { 0x77, 0 }, .brk = { 0xf7, 0 } }, /* 077 */ + { .mk = { 0x78, 0 }, .brk = { 0xf8, 0 } }, /* 078 */ + { .mk = { 0x79, 0 }, .brk = { 0xf9, 0 } }, /* 079 */ + { .mk = { 0x7a, 0 }, .brk = { 0xfa, 0 } }, /* 07a */ + { .mk = { 0x7b, 0 }, .brk = { 0xfb, 0 } }, /* 07b */ + { .mk = { 0x7c, 0 }, .brk = { 0xfc, 0 } }, /* 07c */ + { .mk = { 0x7d, 0 }, .brk = { 0xfd, 0 } }, /* 07d */ + { .mk = { 0x7e, 0 }, .brk = { 0xfe, 0 } }, /* 07e */ + { .mk = { 0x7f, 0 }, .brk = { 0xff, 0 } }, /* 07f */ + { .mk = { 0x80, 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0x81, 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0x82, 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0x85, 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0x86, 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0x87, 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0x88, 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0x89, 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0x8a, 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0x8b, 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0x8c, 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0x8d, 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0x8e, 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0x8f, 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0x90, 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0x91, 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0x92, 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0x93, 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0x94, 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0x95, 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0x96, 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0x97, 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0x98, 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0x99, 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0x9a, 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0x9b, 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0x9c, 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0x9d, 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0x9e, 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0x9f, 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0xa0, 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0xa1, 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0xa2, 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0xa3, 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0xa4, 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0xa5, 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0xa6, 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0xa7, 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0xa8, 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0xa9, 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0xaa, 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0xab, 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0xac, 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0xad, 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0xae, 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0xaf, 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0xb0, 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0xb1, 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0xb2, 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0xb3, 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0xb4, 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0xb5, 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0xb6, 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0xb7, 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0xb8, 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0xb9, 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0xba, 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0xbb, 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0xbc, 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0xbd, 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0xbe, 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0xbf, 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0xc0, 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0xc1, 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0xc2, 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0xc3, 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0xc4, 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0xc5, 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0xc6, 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0xc7, 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0xc8, 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0xc9, 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0xca, 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0xcb, 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0xcc, 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0xcd, 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0xce, 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0xcf, 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0xd0, 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0xd1, 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0xd2, 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0xd3, 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0xd4, 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0xd5, 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0xd6, 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0xd7, 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0xd8, 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0xd9, 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0xda, 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0xdb, 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0xdc, 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0xdd, 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0xde, 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0xdf, 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0xe0, 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0xe1, 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0xe2, 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0xe3, 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0xe4, 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0xe5, 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0xe6, 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0xe7, 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0xe8, 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0xe9, 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0xea, 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0xeb, 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0xec, 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0xed, 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0xee, 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0xef, 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0xf1, 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0xf2, 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0xf3, 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0xf4, 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0xf5, 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0xf6, 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0xf7, 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0xf8, 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0xf9, 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0xfa, 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0xfb, 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0xfc, 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0xfd, 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0xfe, 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0xff, 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = {0xe1, 0x1d, 0 }, .brk = { 0xe1, 0x9d, 0 } }, /* 100 */ + { .mk = {0xe0, 0x01, 0 }, .brk = { 0xe0, 0x81, 0 } }, /* 101 */ + { .mk = {0xe0, 0x02, 0 }, .brk = { 0xe0, 0x82, 0 } }, /* 102 */ + { .mk = {0xe0, 0x03, 0 }, .brk = { 0xe0, 0x83, 0 } }, /* 103 */ + { .mk = {0xe0, 0x04, 0 }, .brk = { 0xe0, 0x84, 0 } }, /* 104 */ + { .mk = {0xe0, 0x05, 0 }, .brk = { 0xe0, 0x85, 0 } }, /* 105 */ + { .mk = {0xe0, 0x06, 0 }, .brk = { 0xe0, 0x86, 0 } }, /* 106 */ + { .mk = {0xe0, 0x07, 0 }, .brk = { 0xe0, 0x87, 0 } }, /* 107 */ + { .mk = {0xe0, 0x08, 0 }, .brk = { 0xe0, 0x88, 0 } }, /* 108 */ + { .mk = {0xe0, 0x09, 0 }, .brk = { 0xe0, 0x89, 0 } }, /* 109 */ + { .mk = {0xe0, 0x0a, 0 }, .brk = { 0xe0, 0x8a, 0 } }, /* 10a */ + { .mk = {0xe0, 0x0b, 0 }, .brk = { 0xe0, 0x8b, 0 } }, /* 10b */ + { .mk = {0xe0, 0x0c, 0 }, .brk = { 0xe0, 0x8c, 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = {0xe0, 0x0e, 0 }, .brk = { 0xe0, 0x8e, 0 } }, /* 10e */ + { .mk = {0xe0, 0x0f, 0 }, .brk = { 0xe0, 0x8f, 0 } }, /* 10f */ + { .mk = {0xe0, 0x10, 0 }, .brk = { 0xe0, 0x90, 0 } }, /* 110 */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0x91, 0 } }, /* 111 */ + { .mk = {0xe0, 0x12, 0 }, .brk = { 0xe0, 0x92, 0 } }, /* 112 */ + { .mk = {0xe0, 0x13, 0 }, .brk = { 0xe0, 0x93, 0 } }, /* 113 */ + { .mk = {0xe0, 0x14, 0 }, .brk = { 0xe0, 0x94, 0 } }, /* 114 */ + { .mk = {0xe0, 0x15, 0 }, .brk = { 0xe0, 0x95, 0 } }, /* 115 */ + { .mk = {0xe0, 0x16, 0 }, .brk = { 0xe0, 0x96, 0 } }, /* 116 */ + { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0x97, 0 } }, /* 117 */ + { .mk = {0xe0, 0x18, 0 }, .brk = { 0xe0, 0x98, 0 } }, /* 118 */ + { .mk = {0xe0, 0x19, 0 }, .brk = { 0xe0, 0x99, 0 } }, /* 119 */ + { .mk = {0xe0, 0x1a, 0 }, .brk = { 0xe0, 0x9a, 0 } }, /* 11a */ + { .mk = {0xe0, 0x1b, 0 }, .brk = { 0xe0, 0x9b, 0 } }, /* 11b */ + { .mk = {0xe0, 0x1c, 0 }, .brk = { 0xe0, 0x9c, 0 } }, /* 11c */ + { .mk = {0xe0, 0x1d, 0 }, .brk = { 0xe0, 0x9d, 0 } }, /* 11d */ + { .mk = {0xe0, 0x1e, 0 }, .brk = { 0xe0, 0x9e, 0 } }, /* 11e */ + { .mk = {0xe0, 0x1f, 0 }, .brk = { 0xe0, 0x9f, 0 } }, /* 11f */ + { .mk = {0xe0, 0x20, 0 }, .brk = { 0xe0, 0xa0, 0 } }, /* 120 */ + { .mk = {0xe0, 0x21, 0 }, .brk = { 0xe0, 0xa1, 0 } }, /* 121 */ + { .mk = {0xe0, 0x22, 0 }, .brk = { 0xe0, 0xa2, 0 } }, /* 122 */ + { .mk = {0xe0, 0x23, 0 }, .brk = { 0xe0, 0xa3, 0 } }, /* 123 */ + { .mk = {0xe0, 0x24, 0 }, .brk = { 0xe0, 0xa4, 0 } }, /* 124 */ + { .mk = {0xe0, 0x25, 0 }, .brk = { 0xe0, 0xa5, 0 } }, /* 125 */ + { .mk = {0xe0, 0x26, 0 }, .brk = { 0xe0, 0xa6, 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = {0xe0, 0x2c, 0 }, .brk = { 0xe0, 0xac, 0 } }, /* 12c */ + { .mk = {0xe0, 0x2d, 0 }, .brk = { 0xe0, 0xad, 0 } }, /* 12d */ + { .mk = {0xe0, 0x2e, 0 }, .brk = { 0xe0, 0xae, 0 } }, /* 12e */ + { .mk = {0xe0, 0x2f, 0 }, .brk = { 0xe0, 0xaf, 0 } }, /* 12f */ + { .mk = {0xe0, 0x30, 0 }, .brk = { 0xe0, 0xb0, 0 } }, /* 130 */ + { .mk = {0xe0, 0x31, 0 }, .brk = { 0xe0, 0xb1, 0 } }, /* 131 */ + { .mk = {0xe0, 0x32, 0 }, .brk = { 0xe0, 0xb2, 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = {0xe0, 0x34, 0 }, .brk = { 0xe0, 0xb4, 0 } }, /* 134 */ + { .mk = {0xe0, 0x35, 0 }, .brk = { 0xe0, 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = {0xe0, 0x37, 0 }, .brk = { 0xe0, 0xb7, 0 } }, /* 137 */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xb8, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = {0xe0, 0x3a, 0 }, .brk = { 0xe0, 0xba, 0 } }, /* 13a */ + { .mk = {0xe0, 0x3b, 0 }, .brk = { 0xe0, 0xbb, 0 } }, /* 13b */ + { .mk = {0xe0, 0x3c, 0 }, .brk = { 0xe0, 0xbc, 0 } }, /* 13c */ + { .mk = {0xe0, 0x3d, 0 }, .brk = { 0xe0, 0xbd, 0 } }, /* 13d */ + { .mk = {0xe0, 0x3e, 0 }, .brk = { 0xe0, 0xbe, 0 } }, /* 13e */ + { .mk = {0xe0, 0x3f, 0 }, .brk = { 0xe0, 0xbf, 0 } }, /* 13f */ + { .mk = {0xe0, 0x40, 0 }, .brk = { 0xe0, 0xc0, 0 } }, /* 140 */ + { .mk = {0xe0, 0x41, 0 }, .brk = { 0xe0, 0xc1, 0 } }, /* 141 */ + { .mk = {0xe0, 0x42, 0 }, .brk = { 0xe0, 0xc2, 0 } }, /* 142 */ + { .mk = {0xe0, 0x43, 0 }, .brk = { 0xe0, 0xc3, 0 } }, /* 143 */ + { .mk = {0xe0, 0x44, 0 }, .brk = { 0xe0, 0xc4, 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = {0xe0, 0x46, 0 }, .brk = { 0xe0, 0xc6, 0 } }, /* 146 */ + { .mk = {0xe0, 0x47, 0 }, .brk = { 0xe0, 0xc7, 0 } }, /* 147 */ + { .mk = {0xe0, 0x48, 0 }, .brk = { 0xe0, 0xc8, 0 } }, /* 148 */ + { .mk = {0xe0, 0x49, 0 }, .brk = { 0xe0, 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = {0xe0, 0x4b, 0 }, .brk = { 0xe0, 0xcb, 0 } }, /* 14b */ + { .mk = {0xe0, 0x4c, 0 }, .brk = { 0xe0, 0xcc, 0 } }, /* 14c */ + { .mk = {0xe0, 0x4d, 0 }, .brk = { 0xe0, 0xcd, 0 } }, /* 14d */ + { .mk = {0xe0, 0x4e, 0 }, .brk = { 0xe0, 0xce, 0 } }, /* 14e */ + { .mk = {0xe0, 0x4f, 0 }, .brk = { 0xe0, 0xcf, 0 } }, /* 14f */ + { .mk = {0xe0, 0x50, 0 }, .brk = { 0xe0, 0xd0, 0 } }, /* 150 */ + { .mk = {0xe0, 0x51, 0 }, .brk = { 0xe0, 0xd1, 0 } }, /* 151 */ + { .mk = {0xe0, 0x52, 0 }, .brk = { 0xe0, 0xd2, 0 } }, /* 152 */ + { .mk = {0xe0, 0x53, 0 }, .brk = { 0xe0, 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = {0xe0, 0x55, 0 }, .brk = { 0xe0, 0xd5, 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */ + { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */ + { .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */ + { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */ + { .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */ + { .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */ + { .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */ + { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */ + { .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */ + { .mk = {0xe0, 0x62, 0 }, .brk = { 0xe0, 0xe2, 0 } }, /* 162 */ + { .mk = {0xe0, 0x63, 0 }, .brk = { 0xe0, 0xe3, 0 } }, /* 163 */ + { .mk = {0xe0, 0x64, 0 }, .brk = { 0xe0, 0xe4, 0 } }, /* 164 */ + { .mk = {0xe0, 0x65, 0 }, .brk = { 0xe0, 0xe5, 0 } }, /* 165 */ + { .mk = {0xe0, 0x66, 0 }, .brk = { 0xe0, 0xe6, 0 } }, /* 166 */ + { .mk = {0xe0, 0x67, 0 }, .brk = { 0xe0, 0xe7, 0 } }, /* 167 */ + { .mk = {0xe0, 0x68, 0 }, .brk = { 0xe0, 0xe8, 0 } }, /* 168 */ + { .mk = {0xe0, 0x69, 0 }, .brk = { 0xe0, 0xe9, 0 } }, /* 169 */ + { .mk = {0xe0, 0x6a, 0 }, .brk = { 0xe0, 0xea, 0 } }, /* 16a */ + { .mk = {0xe0, 0x6b, 0 }, .brk = { 0xe0, 0xeb, 0 } }, /* 16b */ + { .mk = {0xe0, 0x6c, 0 }, .brk = { 0xe0, 0xec, 0 } }, /* 16c */ + { .mk = {0xe0, 0x6d, 0 }, .brk = { 0xe0, 0xed, 0 } }, /* 16d */ + { .mk = {0xe0, 0x6e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = {0xe0, 0x70, 0 }, .brk = { 0xe0, 0xf0, 0 } }, /* 170 */ + { .mk = {0xe0, 0x71, 0 }, .brk = { 0xe0, 0xf1, 0 } }, /* 171 */ + { .mk = {0xe0, 0x72, 0 }, .brk = { 0xe0, 0xf2, 0 } }, /* 172 */ + { .mk = {0xe0, 0x73, 0 }, .brk = { 0xe0, 0xf3, 0 } }, /* 173 */ + { .mk = {0xe0, 0x74, 0 }, .brk = { 0xe0, 0xf4, 0 } }, /* 174 */ + { .mk = {0xe0, 0x75, 0 }, .brk = { 0xe0, 0xf5, 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = {0xe0, 0x77, 0 }, .brk = { 0xe0, 0xf7, 0 } }, /* 177 */ + { .mk = {0xe0, 0x78, 0 }, .brk = { 0xe0, 0xf8, 0 } }, /* 178 */ + { .mk = {0xe0, 0x79, 0 }, .brk = { 0xe0, 0xf9, 0 } }, /* 179 */ + { .mk = {0xe0, 0x7a, 0 }, .brk = { 0xe0, 0xfa, 0 } }, /* 17a */ + { .mk = {0xe0, 0x7b, 0 }, .brk = { 0xe0, 0xfb, 0 } }, /* 17b */ + { .mk = {0xe0, 0x7c, 0 }, .brk = { 0xe0, 0xfc, 0 } }, /* 17c */ + { .mk = {0xe0, 0x7d, 0 }, .brk = { 0xe0, 0xfd, 0 } }, /* 17d */ + { .mk = {0xe0, 0x7e, 0 }, .brk = { 0xe0, 0xfe, 0 } }, /* 17e */ + { .mk = {0xe0, 0x7f, 0 }, .brk = { 0xe0, 0xff, 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = {0xe0, 0xe1, 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = {0xe0, 0xee, 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = {0xe0, 0xf1, 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = {0xe0, 0xfe, 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = {0xe0, 0xff, 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; static const scancode scancode_set2[512] = { // clang-format off - { { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/ - { { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/ - { { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/ - { { 0x4E,0},{ 0xF0,0x4E,0} }, { { 0x55,0},{ 0xF0,0x55,0} }, { { 0x66,0},{ 0xF0,0x66,0} }, { { 0x0D,0},{ 0xF0,0x0D,0} }, /*00c*/ - { { 0x15,0},{ 0xF0,0x15,0} }, { { 0x1D,0},{ 0xF0,0x1D,0} }, { { 0x24,0},{ 0xF0,0x24,0} }, { { 0x2D,0},{ 0xF0,0x2D,0} }, /*010*/ - { { 0x2C,0},{ 0xF0,0x2C,0} }, { { 0x35,0},{ 0xF0,0x35,0} }, { { 0x3C,0},{ 0xF0,0x3C,0} }, { { 0x43,0},{ 0xF0,0x43,0} }, /*014*/ - { { 0x44,0},{ 0xF0,0x44,0} }, { { 0x4D,0},{ 0xF0,0x4D,0} }, { { 0x54,0},{ 0xF0,0x54,0} }, { { 0x5B,0},{ 0xF0,0x5B,0} }, /*018*/ - { { 0x5A,0},{ 0xF0,0x5A,0} }, { { 0x14,0},{ 0xF0,0x14,0} }, { { 0x1C,0},{ 0xF0,0x1C,0} }, { { 0x1B,0},{ 0xF0,0x1B,0} }, /*01c*/ - { { 0x23,0},{ 0xF0,0x23,0} }, { { 0x2B,0},{ 0xF0,0x2B,0} }, { { 0x34,0},{ 0xF0,0x34,0} }, { { 0x33,0},{ 0xF0,0x33,0} }, /*020*/ - { { 0x3B,0},{ 0xF0,0x3B,0} }, { { 0x42,0},{ 0xF0,0x42,0} }, { { 0x4B,0},{ 0xF0,0x4B,0} }, { { 0x4C,0},{ 0xF0,0x4C,0} }, /*024*/ - { { 0x52,0},{ 0xF0,0x52,0} }, { { 0x0E,0},{ 0xF0,0x0E,0} }, { { 0x12,0},{ 0xF0,0x12,0} }, { { 0x5D,0},{ 0xF0,0x5D,0} }, /*028*/ - { { 0x1A,0},{ 0xF0,0x1A,0} }, { { 0x22,0},{ 0xF0,0x22,0} }, { { 0x21,0},{ 0xF0,0x21,0} }, { { 0x2A,0},{ 0xF0,0x2A,0} }, /*02c*/ - { { 0x32,0},{ 0xF0,0x32,0} }, { { 0x31,0},{ 0xF0,0x31,0} }, { { 0x3A,0},{ 0xF0,0x3A,0} }, { { 0x41,0},{ 0xF0,0x41,0} }, /*030*/ - { { 0x49,0},{ 0xF0,0x49,0} }, { { 0x4A,0},{ 0xF0,0x4A,0} }, { { 0x59,0},{ 0xF0,0x59,0} }, { { 0x7C,0},{ 0xF0,0x7C,0} }, /*034*/ - { { 0x11,0},{ 0xF0,0x11,0} }, { { 0x29,0},{ 0xF0,0x29,0} }, { { 0x58,0},{ 0xF0,0x58,0} }, { { 0x05,0},{ 0xF0,0x05,0} }, /*038*/ - { { 0x06,0},{ 0xF0,0x06,0} }, { { 0x04,0},{ 0xF0,0x04,0} }, { { 0x0C,0},{ 0xF0,0x0C,0} }, { { 0x03,0},{ 0xF0,0x03,0} }, /*03c*/ - { { 0x0B,0},{ 0xF0,0x0B,0} }, { { 0x83,0},{ 0xF0,0x83,0} }, { { 0x0A,0},{ 0xF0,0x0A,0} }, { { 0x01,0},{ 0xF0,0x01,0} }, /*040*/ - { { 0x09,0},{ 0xF0,0x09,0} }, { { 0x77,0},{ 0xF0,0x77,0} }, { { 0x7E,0},{ 0xF0,0x7E,0} }, { { 0x6C,0},{ 0xF0,0x6C,0} }, /*044*/ - { { 0x75,0},{ 0xF0,0x75,0} }, { { 0x7D,0},{ 0xF0,0x7D,0} }, { { 0x7B,0},{ 0xF0,0x7B,0} }, { { 0x6B,0},{ 0xF0,0x6B,0} }, /*048*/ - { { 0x73,0},{ 0xF0,0x73,0} }, { { 0x74,0},{ 0xF0,0x74,0} }, { { 0x79,0},{ 0xF0,0x79,0} }, { { 0x69,0},{ 0xF0,0x69,0} }, /*04c*/ - { { 0x72,0},{ 0xF0,0x72,0} }, { { 0x7A,0},{ 0xF0,0x7A,0} }, { { 0x70,0},{ 0xF0,0x70,0} }, { { 0x71,0},{ 0xF0,0x71,0} }, /*050*/ - { { 0x84,0},{ 0xF0,0x84,0} }, { { 0x60,0},{ 0xF0,0x60,0} }, { { 0x61,0},{ 0xF0,0x61,0} }, { { 0x78,0},{ 0xF0,0x78,0} }, /*054*/ - { { 0x07,0},{ 0xF0,0x07,0} }, { { 0x0F,0},{ 0xF0,0x0F,0} }, { { 0x17,0},{ 0xF0,0x17,0} }, { { 0x1F,0},{ 0xF0,0x1F,0} }, /*058*/ - { { 0x27,0},{ 0xF0,0x27,0} }, { { 0x2F,0},{ 0xF0,0x2F,0} }, { { 0x37,0},{ 0xF0,0x37,0} }, { { 0x3F,0},{ 0xF0,0x3F,0} }, /*05c*/ - { { 0x47,0},{ 0xF0,0x47,0} }, { { 0x4F,0},{ 0xF0,0x4F,0} }, { { 0x56,0},{ 0xF0,0x56,0} }, { { 0x5E,0},{ 0xF0,0x5E,0} }, /*060*/ - { { 0x08,0},{ 0xF0,0x08,0} }, { { 0x10,0},{ 0xF0,0x10,0} }, { { 0x18,0},{ 0xF0,0x18,0} }, { { 0x20,0},{ 0xF0,0x20,0} }, /*064*/ - { { 0x28,0},{ 0xF0,0x28,0} }, { { 0x30,0},{ 0xF0,0x30,0} }, { { 0x38,0},{ 0xF0,0x38,0} }, { { 0x40,0},{ 0xF0,0x40,0} }, /*068*/ - { { 0x48,0},{ 0xF0,0x48,0} }, { { 0x50,0},{ 0xF0,0x50,0} }, { { 0x57,0},{ 0xF0,0x57,0} }, { { 0x6F,0},{ 0xF0,0x6F,0} }, /*06c*/ - { { 0x13,0},{ 0xF0,0x13,0} }, { { 0x19,0},{ 0xF0,0x19,0} }, { { 0x39,0},{ 0xF0,0x39,0} }, { { 0x51,0},{ 0xF0,0x51,0} }, /*070*/ - { { 0x53,0},{ 0xF0,0x53,0} }, { { 0x5C,0},{ 0xF0,0x5C,0} }, { { 0x5F,0},{ 0xF0,0x5F,0} }, { { 0x62,0},{ 0xF0,0x62,0} }, /*074*/ - { { 0x63,0},{ 0xF0,0x63,0} }, { { 0x64,0},{ 0xF0,0x64,0} }, { { 0x65,0},{ 0xF0,0x65,0} }, { { 0x67,0},{ 0xF0,0x67,0} }, /*078*/ - { { 0x68,0},{ 0xF0,0x68,0} }, { { 0x6A,0},{ 0xF0,0x6A,0} }, { { 0x6D,0},{ 0xF0,0x6D,0} }, { { 0x6E,0},{ 0xF0,0x6E,0} }, /*07c*/ - - { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ - { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ - { { 0x8c,0},{ 0xf0,0x8c,0} }, { { 0x8d,0},{ 0xf0,0x8d,0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ - { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ - { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ - { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ - { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ - { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ - { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ - { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ - { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ - { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ - { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ - { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ - { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ - { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ - { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ - { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ - { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ - { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ - { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ - { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ - { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ - { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ - { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ - { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ - { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ - { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ - { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ - { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ - - { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ - { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ - { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ - { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ - { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ - { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ - { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ - { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ - { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ - { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ - { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { { 0},{ 0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} }, /*134*/ - { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ - { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ - { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ - { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} }, /*144*/ - { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { { 0},{ 0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} }, /*148*/ - { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} }, /*14c*/ - { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ - { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} }, /*158*/ - { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} }, /*160*/ - { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ - { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ - { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ - { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ - { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ - { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x76, 0 }, .brk = { 0xF0, 0x76, 0 } }, /* 001 */ + { .mk = { 0x16, 0 }, .brk = { 0xF0, 0x16, 0 } }, /* 002 */ + { .mk = { 0x1E, 0 }, .brk = { 0xF0, 0x1E, 0 } }, /* 003 */ + { .mk = { 0x26, 0 }, .brk = { 0xF0, 0x26, 0 } }, /* 004 */ + { .mk = { 0x25, 0 }, .brk = { 0xF0, 0x25, 0 } }, /* 005 */ + { .mk = { 0x2E, 0 }, .brk = { 0xF0, 0x2E, 0 } }, /* 006 */ + { .mk = { 0x36, 0 }, .brk = { 0xF0, 0x36, 0 } }, /* 007 */ + { .mk = { 0x3D, 0 }, .brk = { 0xF0, 0x3D, 0 } }, /* 008 */ + { .mk = { 0x3E, 0 }, .brk = { 0xF0, 0x3E, 0 } }, /* 009 */ + { .mk = { 0x46, 0 }, .brk = { 0xF0, 0x46, 0 } }, /* 00a */ + { .mk = { 0x45, 0 }, .brk = { 0xF0, 0x45, 0 } }, /* 00b */ + { .mk = { 0x4E, 0 }, .brk = { 0xF0, 0x4E, 0 } }, /* 00c */ + { .mk = { 0x55, 0 }, .brk = { 0xF0, 0x55, 0 } }, /* 00d */ + { .mk = { 0x66, 0 }, .brk = { 0xF0, 0x66, 0 } }, /* 00e */ + { .mk = { 0x0D, 0 }, .brk = { 0xF0, 0x0D, 0 } }, /* 00f */ + { .mk = { 0x15, 0 }, .brk = { 0xF0, 0x15, 0 } }, /* 010 */ + { .mk = { 0x1D, 0 }, .brk = { 0xF0, 0x1D, 0 } }, /* 011 */ + { .mk = { 0x24, 0 }, .brk = { 0xF0, 0x24, 0 } }, /* 012 */ + { .mk = { 0x2D, 0 }, .brk = { 0xF0, 0x2D, 0 } }, /* 013 */ + { .mk = { 0x2C, 0 }, .brk = { 0xF0, 0x2C, 0 } }, /* 014 */ + { .mk = { 0x35, 0 }, .brk = { 0xF0, 0x35, 0 } }, /* 015 */ + { .mk = { 0x3C, 0 }, .brk = { 0xF0, 0x3C, 0 } }, /* 016 */ + { .mk = { 0x43, 0 }, .brk = { 0xF0, 0x43, 0 } }, /* 017 */ + { .mk = { 0x44, 0 }, .brk = { 0xF0, 0x44, 0 } }, /* 018 */ + { .mk = { 0x4D, 0 }, .brk = { 0xF0, 0x4D, 0 } }, /* 019 */ + { .mk = { 0x54, 0 }, .brk = { 0xF0, 0x54, 0 } }, /* 01a */ + { .mk = { 0x5B, 0 }, .brk = { 0xF0, 0x5B, 0 } }, /* 01b */ + { .mk = { 0x5A, 0 }, .brk = { 0xF0, 0x5A, 0 } }, /* 01c */ + { .mk = { 0x14, 0 }, .brk = { 0xF0, 0x14, 0 } }, /* 01d */ + { .mk = { 0x1C, 0 }, .brk = { 0xF0, 0x1C, 0 } }, /* 01e */ + { .mk = { 0x1B, 0 }, .brk = { 0xF0, 0x1B, 0 } }, /* 01f */ + { .mk = { 0x23, 0 }, .brk = { 0xF0, 0x23, 0 } }, /* 020 */ + { .mk = { 0x2B, 0 }, .brk = { 0xF0, 0x2B, 0 } }, /* 021 */ + { .mk = { 0x34, 0 }, .brk = { 0xF0, 0x34, 0 } }, /* 022 */ + { .mk = { 0x33, 0 }, .brk = { 0xF0, 0x33, 0 } }, /* 023 */ + { .mk = { 0x3B, 0 }, .brk = { 0xF0, 0x3B, 0 } }, /* 024 */ + { .mk = { 0x42, 0 }, .brk = { 0xF0, 0x42, 0 } }, /* 025 */ + { .mk = { 0x4B, 0 }, .brk = { 0xF0, 0x4B, 0 } }, /* 026 */ + { .mk = { 0x4C, 0 }, .brk = { 0xF0, 0x4C, 0 } }, /* 027 */ + { .mk = { 0x52, 0 }, .brk = { 0xF0, 0x52, 0 } }, /* 028 */ + { .mk = { 0x0E, 0 }, .brk = { 0xF0, 0x0E, 0 } }, /* 029 */ + { .mk = { 0x12, 0 }, .brk = { 0xF0, 0x12, 0 } }, /* 02a */ + { .mk = { 0x5D, 0 }, .brk = { 0xF0, 0x5D, 0 } }, /* 02b */ + { .mk = { 0x1A, 0 }, .brk = { 0xF0, 0x1A, 0 } }, /* 02c */ + { .mk = { 0x22, 0 }, .brk = { 0xF0, 0x22, 0 } }, /* 02d */ + { .mk = { 0x21, 0 }, .brk = { 0xF0, 0x21, 0 } }, /* 02e */ + { .mk = { 0x2A, 0 }, .brk = { 0xF0, 0x2A, 0 } }, /* 02f */ + { .mk = { 0x32, 0 }, .brk = { 0xF0, 0x32, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xF0, 0x31, 0 } }, /* 031 */ + { .mk = { 0x3A, 0 }, .brk = { 0xF0, 0x3A, 0 } }, /* 032 */ + { .mk = { 0x41, 0 }, .brk = { 0xF0, 0x41, 0 } }, /* 033 */ + { .mk = { 0x49, 0 }, .brk = { 0xF0, 0x49, 0 } }, /* 034 */ + { .mk = { 0x4A, 0 }, .brk = { 0xF0, 0x4A, 0 } }, /* 035 */ + { .mk = { 0x59, 0 }, .brk = { 0xF0, 0x59, 0 } }, /* 036 */ + { .mk = { 0x7C, 0 }, .brk = { 0xF0, 0x7C, 0 } }, /* 037 */ + { .mk = { 0x11, 0 }, .brk = { 0xF0, 0x11, 0 } }, /* 038 */ + { .mk = { 0x29, 0 }, .brk = { 0xF0, 0x29, 0 } }, /* 039 */ + { .mk = { 0x58, 0 }, .brk = { 0xF0, 0x58, 0 } }, /* 03a */ + { .mk = { 0x05, 0 }, .brk = { 0xF0, 0x05, 0 } }, /* 03b */ + { .mk = { 0x06, 0 }, .brk = { 0xF0, 0x06, 0 } }, /* 03c */ + { .mk = { 0x04, 0 }, .brk = { 0xF0, 0x04, 0 } }, /* 03d */ + { .mk = { 0x0C, 0 }, .brk = { 0xF0, 0x0C, 0 } }, /* 03e */ + { .mk = { 0x03, 0 }, .brk = { 0xF0, 0x03, 0 } }, /* 03f */ + { .mk = { 0x0B, 0 }, .brk = { 0xF0, 0x0B, 0 } }, /* 040 */ + { .mk = { 0x83, 0 }, .brk = { 0xF0, 0x83, 0 } }, /* 041 */ + { .mk = { 0x0A, 0 }, .brk = { 0xF0, 0x0A, 0 } }, /* 042 */ + { .mk = { 0x01, 0 }, .brk = { 0xF0, 0x01, 0 } }, /* 043 */ + { .mk = { 0x09, 0 }, .brk = { 0xF0, 0x09, 0 } }, /* 044 */ + { .mk = { 0x77, 0 }, .brk = { 0xF0, 0x77, 0 } }, /* 045 */ + { .mk = { 0x7E, 0 }, .brk = { 0xF0, 0x7E, 0 } }, /* 046 */ + { .mk = { 0x6C, 0 }, .brk = { 0xF0, 0x6C, 0 } }, /* 047 */ + { .mk = { 0x75, 0 }, .brk = { 0xF0, 0x75, 0 } }, /* 048 */ + { .mk = { 0x7D, 0 }, .brk = { 0xF0, 0x7D, 0 } }, /* 049 */ + { .mk = { 0x7B, 0 }, .brk = { 0xF0, 0x7B, 0 } }, /* 04a */ + { .mk = { 0x6B, 0 }, .brk = { 0xF0, 0x6B, 0 } }, /* 04b */ + { .mk = { 0x73, 0 }, .brk = { 0xF0, 0x73, 0 } }, /* 04c */ + { .mk = { 0x74, 0 }, .brk = { 0xF0, 0x74, 0 } }, /* 04d */ + { .mk = { 0x79, 0 }, .brk = { 0xF0, 0x79, 0 } }, /* 04e */ + { .mk = { 0x69, 0 }, .brk = { 0xF0, 0x69, 0 } }, /* 04f */ + { .mk = { 0x72, 0 }, .brk = { 0xF0, 0x72, 0 } }, /* 050 */ + { .mk = { 0x7A, 0 }, .brk = { 0xF0, 0x7A, 0 } }, /* 051 */ + { .mk = { 0x70, 0 }, .brk = { 0xF0, 0x70, 0 } }, /* 052 */ + { .mk = { 0x71, 0 }, .brk = { 0xF0, 0x71, 0 } }, /* 053 */ + { .mk = { 0x84, 0 }, .brk = { 0xF0, 0x84, 0 } }, /* 054 */ + { .mk = { 0x60, 0 }, .brk = { 0xF0, 0x60, 0 } }, /* 055 */ + { .mk = { 0x61, 0 }, .brk = { 0xF0, 0x61, 0 } }, /* 056 */ + { .mk = { 0x78, 0 }, .brk = { 0xF0, 0x78, 0 } }, /* 057 */ + { .mk = { 0x07, 0 }, .brk = { 0xF0, 0x07, 0 } }, /* 058 */ + { .mk = { 0x0F, 0 }, .brk = { 0xF0, 0x0F, 0 } }, /* 059 */ + { .mk = { 0x17, 0 }, .brk = { 0xF0, 0x17, 0 } }, /* 05a */ + { .mk = { 0x1F, 0 }, .brk = { 0xF0, 0x1F, 0 } }, /* 05b */ + { .mk = { 0x27, 0 }, .brk = { 0xF0, 0x27, 0 } }, /* 05c */ + { .mk = { 0x2F, 0 }, .brk = { 0xF0, 0x2F, 0 } }, /* 05d */ + { .mk = { 0x37, 0 }, .brk = { 0xF0, 0x37, 0 } }, /* 05e */ + { .mk = { 0x3F, 0 }, .brk = { 0xF0, 0x3F, 0 } }, /* 05f */ + { .mk = { 0x47, 0 }, .brk = { 0xF0, 0x47, 0 } }, /* 060 */ + { .mk = { 0x4F, 0 }, .brk = { 0xF0, 0x4F, 0 } }, /* 061 */ + { .mk = { 0x56, 0 }, .brk = { 0xF0, 0x56, 0 } }, /* 062 */ + { .mk = { 0x5E, 0 }, .brk = { 0xF0, 0x5E, 0 } }, /* 063 */ + { .mk = { 0x08, 0 }, .brk = { 0xF0, 0x08, 0 } }, /* 064 */ + { .mk = { 0x10, 0 }, .brk = { 0xF0, 0x10, 0 } }, /* 065 */ + { .mk = { 0x18, 0 }, .brk = { 0xF0, 0x18, 0 } }, /* 066 */ + { .mk = { 0x20, 0 }, .brk = { 0xF0, 0x20, 0 } }, /* 067 */ + { .mk = { 0x28, 0 }, .brk = { 0xF0, 0x28, 0 } }, /* 068 */ + { .mk = { 0x30, 0 }, .brk = { 0xF0, 0x30, 0 } }, /* 069 */ + { .mk = { 0x38, 0 }, .brk = { 0xF0, 0x38, 0 } }, /* 06a */ + { .mk = { 0x40, 0 }, .brk = { 0xF0, 0x40, 0 } }, /* 06b */ + { .mk = { 0x48, 0 }, .brk = { 0xF0, 0x48, 0 } }, /* 06c */ + { .mk = { 0x50, 0 }, .brk = { 0xF0, 0x50, 0 } }, /* 06d */ + { .mk = { 0x57, 0 }, .brk = { 0xF0, 0x57, 0 } }, /* 06e */ + { .mk = { 0x6F, 0 }, .brk = { 0xF0, 0x6F, 0 } }, /* 06f */ + { .mk = { 0x13, 0 }, .brk = { 0xF0, 0x13, 0 } }, /* 070 */ + { .mk = { 0x19, 0 }, .brk = { 0xF0, 0x19, 0 } }, /* 071 */ + { .mk = { 0x39, 0 }, .brk = { 0xF0, 0x39, 0 } }, /* 072 */ + { .mk = { 0x51, 0 }, .brk = { 0xF0, 0x51, 0 } }, /* 073 */ + { .mk = { 0x53, 0 }, .brk = { 0xF0, 0x53, 0 } }, /* 074 */ + { .mk = { 0x5C, 0 }, .brk = { 0xF0, 0x5C, 0 } }, /* 075 */ + { .mk = { 0x5F, 0 }, .brk = { 0xF0, 0x5F, 0 } }, /* 076 */ + { .mk = { 0x62, 0 }, .brk = { 0xF0, 0x62, 0 } }, /* 077 */ + { .mk = { 0x63, 0 }, .brk = { 0xF0, 0x63, 0 } }, /* 078 */ + { .mk = { 0x64, 0 }, .brk = { 0xF0, 0x64, 0 } }, /* 079 */ + { .mk = { 0x65, 0 }, .brk = { 0xF0, 0x65, 0 } }, /* 07a */ + { .mk = { 0x67, 0 }, .brk = { 0xF0, 0x67, 0 } }, /* 07b */ + { .mk = { 0x68, 0 }, .brk = { 0xF0, 0x68, 0 } }, /* 07c */ + { .mk = { 0x6A, 0 }, .brk = { 0xF0, 0x6A, 0 } }, /* 07d */ + { .mk = { 0x6D, 0 }, .brk = { 0xF0, 0x6D, 0 } }, /* 07e */ + { .mk = { 0x6E, 0 }, .brk = { 0xF0, 0x6E, 0 } }, /* 07f */ + { .mk = { 0x80, 0 }, .brk = { 0xf0, 0x80, 0 } }, /* 080 */ + { .mk = { 0x81, 0 }, .brk = { 0xf0, 0x81, 0 } }, /* 081 */ + { .mk = { 0x82, 0 }, .brk = { 0xf0, 0x82, 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0x85, 0 }, .brk = { 0xf0, 0x54, 0 } }, /* 085 */ + { .mk = { 0x86, 0 }, .brk = { 0xf0, 0x86, 0 } }, /* 086 */ + { .mk = { 0x87, 0 }, .brk = { 0xf0, 0x87, 0 } }, /* 087 */ + { .mk = { 0x88, 0 }, .brk = { 0xf0, 0x88, 0 } }, /* 088 */ + { .mk = { 0x89, 0 }, .brk = { 0xf0, 0x89, 0 } }, /* 089 */ + { .mk = { 0x8a, 0 }, .brk = { 0xf0, 0x8a, 0 } }, /* 08a */ + { .mk = { 0x8b, 0 }, .brk = { 0xf0, 0x8b, 0 } }, /* 08b */ + { .mk = { 0x8c, 0 }, .brk = { 0xf0, 0x8c, 0 } }, /* 08c */ + { .mk = { 0x8d, 0 }, .brk = { 0xf0, 0x8d, 0 } }, /* 08d */ + { .mk = { 0x8e, 0 }, .brk = { 0xf0, 0x8e, 0 } }, /* 08e */ + { .mk = { 0x8f, 0 }, .brk = { 0xf0, 0x8f, 0 } }, /* 08f */ + { .mk = { 0x90, 0 }, .brk = { 0xf0, 0x90, 0 } }, /* 090 */ + { .mk = { 0x91, 0 }, .brk = { 0xf0, 0x91, 0 } }, /* 091 */ + { .mk = { 0x92, 0 }, .brk = { 0xf0, 0x92, 0 } }, /* 092 */ + { .mk = { 0x93, 0 }, .brk = { 0xf0, 0x93, 0 } }, /* 093 */ + { .mk = { 0x94, 0 }, .brk = { 0xf0, 0x94, 0 } }, /* 094 */ + { .mk = { 0x95, 0 }, .brk = { 0xf0, 0x95, 0 } }, /* 095 */ + { .mk = { 0x96, 0 }, .brk = { 0xf0, 0x96, 0 } }, /* 096 */ + { .mk = { 0x97, 0 }, .brk = { 0xf0, 0x97, 0 } }, /* 097 */ + { .mk = { 0x98, 0 }, .brk = { 0xf0, 0x98, 0 } }, /* 098 */ + { .mk = { 0x99, 0 }, .brk = { 0xf0, 0x99, 0 } }, /* 099 */ + { .mk = { 0x9a, 0 }, .brk = { 0xf0, 0x9a, 0 } }, /* 09a */ + { .mk = { 0x9b, 0 }, .brk = { 0xf0, 0x9b, 0 } }, /* 09b */ + { .mk = { 0x9c, 0 }, .brk = { 0xf0, 0x9c, 0 } }, /* 09c */ + { .mk = { 0x9d, 0 }, .brk = { 0xf0, 0x9d, 0 } }, /* 09d */ + { .mk = { 0x9e, 0 }, .brk = { 0xf0, 0x9e, 0 } }, /* 09e */ + { .mk = { 0x9f, 0 }, .brk = { 0xf0, 0x9f, 0 } }, /* 09f */ + { .mk = { 0xa0, 0 }, .brk = { 0xf0, 0xa0, 0 } }, /* 0a0 */ + { .mk = { 0xa1, 0 }, .brk = { 0xf0, 0xa1, 0 } }, /* 0a1 */ + { .mk = { 0xa2, 0 }, .brk = { 0xf0, 0xa2, 0 } }, /* 0a2 */ + { .mk = { 0xa3, 0 }, .brk = { 0xf0, 0xa3, 0 } }, /* 0a3 */ + { .mk = { 0xa4, 0 }, .brk = { 0xf0, 0xa4, 0 } }, /* 0a4 */ + { .mk = { 0xa5, 0 }, .brk = { 0xf0, 0xa5, 0 } }, /* 0a5 */ + { .mk = { 0xa6, 0 }, .brk = { 0xf0, 0xa6, 0 } }, /* 0a6 */ + { .mk = { 0xa7, 0 }, .brk = { 0xf0, 0xa7, 0 } }, /* 0a7 */ + { .mk = { 0xa8, 0 }, .brk = { 0xf0, 0xa8, 0 } }, /* 0a8 */ + { .mk = { 0xa9, 0 }, .brk = { 0xf0, 0xa9, 0 } }, /* 0a9 */ + { .mk = { 0xaa, 0 }, .brk = { 0xf0, 0xaa, 0 } }, /* 0aa */ + { .mk = { 0xab, 0 }, .brk = { 0xf0, 0xab, 0 } }, /* 0ab */ + { .mk = { 0xac, 0 }, .brk = { 0xf0, 0xac, 0 } }, /* 0ac */ + { .mk = { 0xad, 0 }, .brk = { 0xf0, 0xad, 0 } }, /* 0ad */ + { .mk = { 0xae, 0 }, .brk = { 0xf0, 0xae, 0 } }, /* 0ae */ + { .mk = { 0xaf, 0 }, .brk = { 0xf0, 0xaf, 0 } }, /* 0af */ + { .mk = { 0xb0, 0 }, .brk = { 0xf0, 0xb0, 0 } }, /* 0b0 */ + { .mk = { 0xb1, 0 }, .brk = { 0xf0, 0xb1, 0 } }, /* 0b1 */ + { .mk = { 0xb2, 0 }, .brk = { 0xf0, 0xb2, 0 } }, /* 0b2 */ + { .mk = { 0xb3, 0 }, .brk = { 0xf0, 0xb3, 0 } }, /* 0b3 */ + { .mk = { 0xb4, 0 }, .brk = { 0xf0, 0xb4, 0 } }, /* 0b4 */ + { .mk = { 0xb5, 0 }, .brk = { 0xf0, 0xb5, 0 } }, /* 0b5 */ + { .mk = { 0xb6, 0 }, .brk = { 0xf0, 0xb6, 0 } }, /* 0b6 */ + { .mk = { 0xb7, 0 }, .brk = { 0xf0, 0xb7, 0 } }, /* 0b7 */ + { .mk = { 0xb8, 0 }, .brk = { 0xf0, 0xb8, 0 } }, /* 0b8 */ + { .mk = { 0xb9, 0 }, .brk = { 0xf0, 0xb9, 0 } }, /* 0b9 */ + { .mk = { 0xba, 0 }, .brk = { 0xf0, 0xba, 0 } }, /* 0ba */ + { .mk = { 0xbb, 0 }, .brk = { 0xf0, 0xbb, 0 } }, /* 0bb */ + { .mk = { 0xbc, 0 }, .brk = { 0xf0, 0xbc, 0 } }, /* 0bc */ + { .mk = { 0xbd, 0 }, .brk = { 0xf0, 0xbd, 0 } }, /* 0bd */ + { .mk = { 0xbe, 0 }, .brk = { 0xf0, 0xbe, 0 } }, /* 0be */ + { .mk = { 0xbf, 0 }, .brk = { 0xf0, 0xbf, 0 } }, /* 0bf */ + { .mk = { 0xc0, 0 }, .brk = { 0xf0, 0xc0, 0 } }, /* 0c0 */ + { .mk = { 0xc1, 0 }, .brk = { 0xf0, 0xc1, 0 } }, /* 0c1 */ + { .mk = { 0xc2, 0 }, .brk = { 0xf0, 0xc2, 0 } }, /* 0c2 */ + { .mk = { 0xc3, 0 }, .brk = { 0xf0, 0xc3, 0 } }, /* 0c3 */ + { .mk = { 0xc4, 0 }, .brk = { 0xf0, 0xc4, 0 } }, /* 0c4 */ + { .mk = { 0xc5, 0 }, .brk = { 0xf0, 0xc5, 0 } }, /* 0c5 */ + { .mk = { 0xc6, 0 }, .brk = { 0xf0, 0xc6, 0 } }, /* 0c6 */ + { .mk = { 0xc7, 0 }, .brk = { 0xf0, 0xc7, 0 } }, /* 0c7 */ + { .mk = { 0xc8, 0 }, .brk = { 0xf0, 0xc8, 0 } }, /* 0c8 */ + { .mk = { 0xc9, 0 }, .brk = { 0xf0, 0xc9, 0 } }, /* 0c9 */ + { .mk = { 0xca, 0 }, .brk = { 0xf0, 0xca, 0 } }, /* 0ca */ + { .mk = { 0xcb, 0 }, .brk = { 0xf0, 0xcb, 0 } }, /* 0cb */ + { .mk = { 0xcc, 0 }, .brk = { 0xf0, 0xcc, 0 } }, /* 0cc */ + { .mk = { 0xcd, 0 }, .brk = { 0xf0, 0xcd, 0 } }, /* 0cd */ + { .mk = { 0xce, 0 }, .brk = { 0xf0, 0xce, 0 } }, /* 0ce */ + { .mk = { 0xcf, 0 }, .brk = { 0xf0, 0xcf, 0 } }, /* 0cf */ + { .mk = { 0xd0, 0 }, .brk = { 0xf0, 0xd0, 0 } }, /* 0d0 */ + { .mk = { 0xd1, 0 }, .brk = { 0xf0, 0xd0, 0 } }, /* 0d1 */ + { .mk = { 0xd2, 0 }, .brk = { 0xf0, 0xd2, 0 } }, /* 0d2 */ + { .mk = { 0xd3, 0 }, .brk = { 0xf0, 0xd3, 0 } }, /* 0d3 */ + { .mk = { 0xd4, 0 }, .brk = { 0xf0, 0xd4, 0 } }, /* 0d4 */ + { .mk = { 0xd5, 0 }, .brk = { 0xf0, 0xd5, 0 } }, /* 0d5 */ + { .mk = { 0xd6, 0 }, .brk = { 0xf0, 0xd6, 0 } }, /* 0d6 */ + { .mk = { 0xd7, 0 }, .brk = { 0xf0, 0xd7, 0 } }, /* 0d7 */ + { .mk = { 0xd8, 0 }, .brk = { 0xf0, 0xd8, 0 } }, /* 0d8 */ + { .mk = { 0xd9, 0 }, .brk = { 0xf0, 0xd9, 0 } }, /* 0d9 */ + { .mk = { 0xda, 0 }, .brk = { 0xf0, 0xda, 0 } }, /* 0da */ + { .mk = { 0xdb, 0 }, .brk = { 0xf0, 0xdb, 0 } }, /* 0db */ + { .mk = { 0xdc, 0 }, .brk = { 0xf0, 0xdc, 0 } }, /* 0dc */ + { .mk = { 0xdd, 0 }, .brk = { 0xf0, 0xdd, 0 } }, /* 0dd */ + { .mk = { 0xde, 0 }, .brk = { 0xf0, 0xde, 0 } }, /* 0de */ + { .mk = { 0xdf, 0 }, .brk = { 0xf0, 0xdf, 0 } }, /* 0df */ + { .mk = { 0xe0, 0 }, .brk = { 0xf0, 0xe0, 0 } }, /* 0e0 */ + { .mk = { 0xe1, 0 }, .brk = { 0xf0, 0xe1, 0 } }, /* 0e1 */ + { .mk = { 0xe2, 0 }, .brk = { 0xf0, 0xe2, 0 } }, /* 0e2 */ + { .mk = { 0xe3, 0 }, .brk = { 0xf0, 0xe3, 0 } }, /* 0e3 */ + { .mk = { 0xe4, 0 }, .brk = { 0xf0, 0xe4, 0 } }, /* 0e4 */ + { .mk = { 0xe5, 0 }, .brk = { 0xf0, 0xe5, 0 } }, /* 0e5 */ + { .mk = { 0xe6, 0 }, .brk = { 0xf0, 0xe6, 0 } }, /* 0e6 */ + { .mk = { 0xe7, 0 }, .brk = { 0xf0, 0xe7, 0 } }, /* 0e7 */ + { .mk = { 0xe8, 0 }, .brk = { 0xf0, 0xe8, 0 } }, /* 0e8 */ + { .mk = { 0xe9, 0 }, .brk = { 0xf0, 0xe9, 0 } }, /* 0e9 */ + { .mk = { 0xea, 0 }, .brk = { 0xf0, 0xea, 0 } }, /* 0ea */ + { .mk = { 0xeb, 0 }, .brk = { 0xf0, 0xeb, 0 } }, /* 0eb */ + { .mk = { 0xec, 0 }, .brk = { 0xf0, 0xec, 0 } }, /* 0ec */ + { .mk = { 0xed, 0 }, .brk = { 0xf0, 0xed, 0 } }, /* 0ed */ + { .mk = { 0xee, 0 }, .brk = { 0xf0, 0xee, 0 } }, /* 0ee */ + { .mk = { 0xef, 0 }, .brk = { 0xf0, 0xef, 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0xf1, 0 }, .brk = { 0xf0, 0xf1, 0 } }, /* 0f1 */ + { .mk = { 0xf2, 0 }, .brk = { 0xf0, 0xf2, 0 } }, /* 0f2 */ + { .mk = { 0xf3, 0 }, .brk = { 0xf0, 0xf3, 0 } }, /* 0f3 */ + { .mk = { 0xf4, 0 }, .brk = { 0xf0, 0xf4, 0 } }, /* 0f4 */ + { .mk = { 0xf5, 0 }, .brk = { 0xf0, 0xf5, 0 } }, /* 0f5 */ + { .mk = { 0xf6, 0 }, .brk = { 0xf0, 0xf6, 0 } }, /* 0f6 */ + { .mk = { 0xf7, 0 }, .brk = { 0xf0, 0xf7, 0 } }, /* 0f7 */ + { .mk = { 0xf8, 0 }, .brk = { 0xf0, 0xf8, 0 } }, /* 0f8 */ + { .mk = { 0xf9, 0 }, .brk = { 0xf0, 0xf9, 0 } }, /* 0f9 */ + { .mk = { 0xfa, 0 }, .brk = { 0xf0, 0xfa, 0 } }, /* 0fa */ + { .mk = { 0xfb, 0 }, .brk = { 0xf0, 0xfb, 0 } }, /* 0fb */ + { .mk = { 0xfc, 0 }, .brk = { 0xf0, 0xfc, 0 } }, /* 0fc */ + { .mk = { 0xfd, 0 }, .brk = { 0xf0, 0xfd, 0 } }, /* 0fd */ + { .mk = { 0xfe, 0 }, .brk = { 0xf0, 0xfe, 0 } }, /* 0fe */ + { .mk = { 0xff, 0 }, .brk = { 0xf0, 0xff, 0 } }, /* 0ff */ + { .mk = {0xe1, 0x14, 0 }, .brk = { 0xe1, 0xf0, 0x14, 0 } }, /* 100 */ + { .mk = {0xe0, 0x76, 0 }, .brk = { 0xe0, 0xF0, 0x76, 0 } }, /* 101 */ + { .mk = {0xe0, 0x16, 0 }, .brk = { 0xe0, 0xF0, 0x16, 0 } }, /* 102 */ + { .mk = {0xe0, 0x1E, 0 }, .brk = { 0xe0, 0xF0, 0x1E, 0 } }, /* 103 */ + { .mk = {0xe0, 0x26, 0 }, .brk = { 0xe0, 0xF0, 0x26, 0 } }, /* 104 */ + { .mk = {0xe0, 0x25, 0 }, .brk = { 0xe0, 0xF0, 0x25, 0 } }, /* 105 */ + { .mk = {0xe0, 0x2E, 0 }, .brk = { 0xe0, 0xF0, 0x2E, 0 } }, /* 106 */ + { .mk = {0xe0, 0x36, 0 }, .brk = { 0xe0, 0xF0, 0x36, 0 } }, /* 107 */ + { .mk = {0xe0, 0x3D, 0 }, .brk = { 0xe0, 0xF0, 0x3D, 0 } }, /* 108 */ + { .mk = {0xe0, 0x3E, 0 }, .brk = { 0xe0, 0xF0, 0x3E, 0 } }, /* 109 */ + { .mk = {0xe0, 0x46, 0 }, .brk = { 0xe0, 0xF0, 0x46, 0 } }, /* 10a */ + { .mk = {0xe0, 0x45, 0 }, .brk = { 0xe0, 0xF0, 0x45, 0 } }, /* 10b */ + { .mk = {0xe0, 0x4E, 0 }, .brk = { 0xe0, 0xF0, 0x4E, 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = {0xe0, 0x66, 0 }, .brk = { 0xe0, 0xF0, 0x66, 0 } }, /* 10e */ + { .mk = {0xe0, 0x0D, 0 }, .brk = { 0xe0, 0xF0, 0x0D, 0 } }, /* 10f */ + { .mk = {0xe0, 0x15, 0 }, .brk = { 0xe0, 0xF0, 0x15, 0 } }, /* 110 */ + { .mk = {0xe0, 0x1D, 0 }, .brk = { 0xe0, 0xF0, 0x1D, 0 } }, /* 112 */ + { .mk = {0xe0, 0x24, 0 }, .brk = { 0xe0, 0xF0, 0x24, 0 } }, /* 113 */ + { .mk = {0xe0, 0x2D, 0 }, .brk = { 0xe0, 0xF0, 0x2D, 0 } }, /* 113 */ + { .mk = {0xe0, 0x2C, 0 }, .brk = { 0xe0, 0xF0, 0x2C, 0 } }, /* 114 */ + { .mk = {0xe0, 0x35, 0 }, .brk = { 0xe0, 0xF0, 0x35, 0 } }, /* 115 */ + { .mk = {0xe0, 0x3C, 0 }, .brk = { 0xe0, 0xF0, 0x3C, 0 } }, /* 116 */ + { .mk = {0xe0, 0x43, 0 }, .brk = { 0xe0, 0xF0, 0x43, 0 } }, /* 117 */ + { .mk = {0xe0, 0x44, 0 }, .brk = { 0xe0, 0xF0, 0x44, 0 } }, /* 118 */ + { .mk = {0xe0, 0x4D, 0 }, .brk = { 0xe0, 0xF0, 0x4D, 0 } }, /* 119 */ + { .mk = {0xe0, 0x54, 0 }, .brk = { 0xe0, 0xF0, 0x54, 0 } }, /* 11a */ + { .mk = {0xe0, 0x5B, 0 }, .brk = { 0xe0, 0xF0, 0x5B, 0 } }, /* 11b */ + { .mk = {0xe0, 0x5A, 0 }, .brk = { 0xe0, 0xF0, 0x5A, 0 } }, /* 11c */ + { .mk = {0xe0, 0x14, 0 }, .brk = { 0xe0, 0xF0, 0x14, 0 } }, /* 11d */ + { .mk = {0xe0, 0x1C, 0 }, .brk = { 0xe0, 0xF0, 0x1C, 0 } }, /* 11e */ + { .mk = {0xe0, 0x1B, 0 }, .brk = { 0xe0, 0xF0, 0x1B, 0 } }, /* 11f */ + { .mk = {0xe0, 0x23, 0 }, .brk = { 0xe0, 0xF0, 0x23, 0 } }, /* 120 */ + { .mk = {0xe0, 0x2B, 0 }, .brk = { 0xe0, 0xF0, 0x2B, 0 } }, /* 121 */ + { .mk = {0xe0, 0x34, 0 }, .brk = { 0xe0, 0xF0, 0x34, 0 } }, /* 122 */ + { .mk = {0xe0, 0x33, 0 }, .brk = { 0xe0, 0xF0, 0x33, 0 } }, /* 123 */ + { .mk = {0xe0, 0x3B, 0 }, .brk = { 0xe0, 0xF0, 0x3B, 0 } }, /* 124 */ + { .mk = {0xe0, 0x42, 0 }, .brk = { 0xe0, 0xF0, 0x42, 0 } }, /* 125 */ + { .mk = {0xe0, 0x4B, 0 }, .brk = { 0xe0, 0xF0, 0x4B, 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = {0xe0, 0x1A, 0 }, .brk = { 0xe0, 0xF0, 0x1A, 0 } }, /* 12c */ + { .mk = {0xe0, 0x22, 0 }, .brk = { 0xe0, 0xF0, 0x22, 0 } }, /* 12d */ + { .mk = {0xe0, 0x21, 0 }, .brk = { 0xe0, 0xF0, 0x21, 0 } }, /* 12e */ + { .mk = {0xe0, 0x2A, 0 }, .brk = { 0xe0, 0xF0, 0x2A, 0 } }, /* 12f */ + { .mk = {0xe0, 0x32, 0 }, .brk = { 0xe0, 0xF0, 0x32, 0 } }, /* 130 */ + { .mk = {0xe0, 0x31, 0 }, .brk = { 0xe0, 0xF0, 0x31, 0 } }, /* 131 */ + { .mk = {0xe0, 0x3A, 0 }, .brk = { 0xe0, 0xF0, 0x3A, 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = {0xe0, 0x49, 0 }, .brk = { 0xe0, 0xF0, 0x49, 0 } }, /* 134 */ + { .mk = {0xe0, 0x4A, 0 }, .brk = { 0xe0, 0xF0, 0x4A, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = {0xe0, 0x7C, 0 }, .brk = { 0xe0, 0xF0, 0x7C, 0 } }, /* 137 */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0xF0, 0x11, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xF0, 0x58, 0 } }, /* 13a */ + { .mk = {0xe0, 0x05, 0 }, .brk = { 0xe0, 0xF0, 0x05, 0 } }, /* 13b */ + { .mk = {0xe0, 0x06, 0 }, .brk = { 0xe0, 0xF0, 0x06, 0 } }, /* 13c */ + { .mk = {0xe0, 0x04, 0 }, .brk = { 0xe0, 0xF0, 0x04, 0 } }, /* 13d */ + { .mk = {0xe0, 0x0C, 0 }, .brk = { 0xe0, 0xF0, 0x0C, 0 } }, /* 13e */ + { .mk = {0xe0, 0x03, 0 }, .brk = { 0xe0, 0xF0, 0x03, 0 } }, /* 13f */ + { .mk = {0xe0, 0x0B, 0 }, .brk = { 0xe0, 0xF0, 0x0B, 0 } }, /* 140 */ + { .mk = {0xe0, 0x02, 0 }, .brk = { 0xe0, 0xF0, 0x02, 0 } }, /* 141 */ + { .mk = {0xe0, 0x0A, 0 }, .brk = { 0xe0, 0xF0, 0x0A, 0 } }, /* 142 */ + { .mk = {0xe0, 0x01, 0 }, .brk = { 0xe0, 0xF0, 0x01, 0 } }, /* 143 */ + { .mk = {0xe0, 0x09, 0 }, .brk = { 0xe0, 0xF0, 0x09, 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = {0xe0, 0x7E, 0 }, .brk = { 0xe0, 0xF0, 0x7E, 0 } }, /* 146 */ + { .mk = {0xe0, 0x6C, 0 }, .brk = { 0xe0, 0xF0, 0x6C, 0 } }, /* 147 */ + { .mk = {0xe0, 0x75, 0 }, .brk = { 0xe0, 0xF0, 0x75, 0 } }, /* 148 */ + { .mk = {0xe0, 0x7D, 0 }, .brk = { 0xe0, 0xF0, 0x7D, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = {0xe0, 0x6B, 0 }, .brk = { 0xe0, 0xF0, 0x6B, 0 } }, /* 14b */ + { .mk = {0xe0, 0x73, 0 }, .brk = { 0xe0, 0xF0, 0x73, 0 } }, /* 14c */ + { .mk = {0xe0, 0x74, 0 }, .brk = { 0xe0, 0xF0, 0x74, 0 } }, /* 14d */ + { .mk = {0xe0, 0x79, 0 }, .brk = { 0xe0, 0xF0, 0x79, 0 } }, /* 14e */ + { .mk = {0xe0, 0x69, 0 }, .brk = { 0xe0, 0xF0, 0x69, 0 } }, /* 14f */ + { .mk = {0xe0, 0x72, 0 }, .brk = { 0xe0, 0xF0, 0x72, 0 } }, /* 150 */ + { .mk = {0xe0, 0x7A, 0 }, .brk = { 0xe0, 0xF0, 0x7A, 0 } }, /* 151 */ + { .mk = {0xe0, 0x70, 0 }, .brk = { 0xe0, 0xF0, 0x70, 0 } }, /* 152 */ + { .mk = {0xe0, 0x71, 0 }, .brk = { 0xe0, 0xF0, 0x71, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = {0xe0, 0x60, 0 }, .brk = { 0xe0, 0xF0, 0x60, 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = {0xe0, 0x78, 0 }, .brk = { 0xe0, 0xF0, 0x78, 0 } }, /* 157 */ + { .mk = {0xe0, 0x07, 0 }, .brk = { 0xe0, 0xF0, 0x07, 0 } }, /* 158 */ + { .mk = {0xe0, 0x0F, 0 }, .brk = { 0xe0, 0xF0, 0x0F, 0 } }, /* 159 */ + { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0xF0, 0x17, 0 } }, /* 15a */ + { .mk = {0xe0, 0x1F, 0 }, .brk = { 0xe0, 0xF0, 0x1F, 0 } }, /* 15b */ + { .mk = {0xe0, 0x27, 0 }, .brk = { 0xe0, 0xF0, 0x27, 0 } }, /* 15c */ + { .mk = {0xe0, 0x2F, 0 }, .brk = { 0xe0, 0xF0, 0x2F, 0 } }, /* 15d */ + { .mk = {0xe0, 0x37, 0 }, .brk = { 0xe0, 0xF0, 0x37, 0 } }, /* 15e */ + { .mk = {0xe0, 0x3F, 0 }, .brk = { 0xe0, 0xF0, 0x3F, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = {0xe0, 0x4F, 0 }, .brk = { 0xe0, 0xF0, 0x4F, 0 } }, /* 161 */ + { .mk = {0xe0, 0x56, 0 }, .brk = { 0xe0, 0xF0, 0x56, 0 } }, /* 162 */ + { .mk = {0xe0, 0x5E, 0 }, .brk = { 0xe0, 0xF0, 0x5E, 0 } }, /* 163 */ + { .mk = {0xe0, 0x08, 0 }, .brk = { 0xe0, 0xF0, 0x08, 0 } }, /* 164 */ + { .mk = {0xe0, 0x10, 0 }, .brk = { 0xe0, 0xF0, 0x10, 0 } }, /* 165 */ + { .mk = {0xe0, 0x18, 0 }, .brk = { 0xe0, 0xF0, 0x18, 0 } }, /* 166 */ + { .mk = {0xe0, 0x20, 0 }, .brk = { 0xe0, 0xF0, 0x20, 0 } }, /* 167 */ + { .mk = {0xe0, 0x28, 0 }, .brk = { 0xe0, 0xF0, 0x28, 0 } }, /* 168 */ + { .mk = {0xe0, 0x30, 0 }, .brk = { 0xe0, 0xF0, 0x30, 0 } }, /* 169 */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xF0, 0x38, 0 } }, /* 16a */ + { .mk = {0xe0, 0x40, 0 }, .brk = { 0xe0, 0xF0, 0x40, 0 } }, /* 16b */ + { .mk = {0xe0, 0x48, 0 }, .brk = { 0xe0, 0xF0, 0x48, 0 } }, /* 16c */ + { .mk = {0xe0, 0x50, 0 }, .brk = { 0xe0, 0xF0, 0x50, 0 } }, /* 16d */ + { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xF0, 0x57, 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = {0xe0, 0x13, 0 }, .brk = { 0xe0, 0xF0, 0x13, 0 } }, /* 170 */ + { .mk = {0xe0, 0x19, 0 }, .brk = { 0xe0, 0xF0, 0x19, 0 } }, /* 171 */ + { .mk = {0xe0, 0x39, 0 }, .brk = { 0xe0, 0xF0, 0x39, 0 } }, /* 172 */ + { .mk = {0xe0, 0x51, 0 }, .brk = { 0xe0, 0xF0, 0x51, 0 } }, /* 173 */ + { .mk = {0xe0, 0x53, 0 }, .brk = { 0xe0, 0xF0, 0x53, 0 } }, /* 174 */ + { .mk = {0xe0, 0x5C, 0 }, .brk = { 0xe0, 0xF0, 0x5C, 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = {0xe0, 0x62, 0 }, .brk = { 0xe0, 0xF0, 0x62, 0 } }, /* 177 */ + { .mk = {0xe0, 0x63, 0 }, .brk = { 0xe0, 0xF0, 0x63, 0 } }, /* 178 */ + { .mk = {0xe0, 0x64, 0 }, .brk = { 0xe0, 0xF0, 0x64, 0 } }, /* 179 */ + { .mk = {0xe0, 0x65, 0 }, .brk = { 0xe0, 0xF0, 0x65, 0 } }, /* 17a */ + { .mk = {0xe0, 0x67, 0 }, .brk = { 0xe0, 0xF0, 0x67, 0 } }, /* 17b */ + { .mk = {0xe0, 0x68, 0 }, .brk = { 0xe0, 0xF0, 0x68, 0 } }, /* 17c */ + { .mk = {0xe0, 0x6A, 0 }, .brk = { 0xe0, 0xF0, 0x6A, 0 } }, /* 17d */ + { .mk = {0xe0, 0x6D, 0 }, .brk = { 0xe0, 0xF0, 0x6D, 0 } }, /* 17e */ + { .mk = {0xe0, 0x6E, 0 }, .brk = { 0xe0, 0xF0, 0x6E, 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cv */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = {0xe0, 0xe1, 0 }, .brk = { 0xe0, 0xF0, 0xE1, 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = {0xe0, 0xee, 0 }, .brk = { 0xe0, 0xF0, 0xEE, 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = {0xe0, 0xf1, 0 }, .brk = { 0xe0, 0xF0, 0xF1, 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = {0xe0, 0xfe, 0 }, .brk = { 0xe0, 0xF0, 0xFE, 0 } }, /* 1fe */ + { .mk = {0xe0, 0xff, 0 }, .brk = { 0xe0, 0xF0, 0xFF, 0 } } /* 1ff */ // clang-format on }; static const scancode scancode_set3[512] = { // clang-format off - { { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/ - { { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/ - { { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/ - { { 0x4E,0},{ 0xf0,0x4E,0} }, { { 0x55,0},{ 0xf0,0x55,0} }, { { 0x66,0},{ 0xf0,0x66,0} }, { { 0x0D,0},{ 0xf0,0x0D,0} }, /*00c*/ - { { 0x15,0},{ 0xf0,0x15,0} }, { { 0x1D,0},{ 0xf0,0x1D,0} }, { { 0x24,0},{ 0xf0,0x24,0} }, { { 0x2D,0},{ 0xf0,0x2D,0} }, /*010*/ - { { 0x2C,0},{ 0xf0,0x2C,0} }, { { 0x35,0},{ 0xf0,0x35,0} }, { { 0x3C,0},{ 0xf0,0x3C,0} }, { { 0x43,0},{ 0xf0,0x43,0} }, /*014*/ - { { 0x44,0},{ 0xf0,0x44,0} }, { { 0x4D,0},{ 0xf0,0x4D,0} }, { { 0x54,0},{ 0xf0,0x54,0} }, { { 0x5B,0},{ 0xf0,0x5B,0} }, /*018*/ - { { 0x5A,0},{ 0xf0,0x5A,0} }, { { 0x11,0},{ 0xf0,0x11,0} }, { { 0x1C,0},{ 0xf0,0x1C,0} }, { { 0x1B,0},{ 0xf0,0x1B,0} }, /*01c*/ - { { 0x23,0},{ 0xf0,0x23,0} }, { { 0x2B,0},{ 0xf0,0x2B,0} }, { { 0x34,0},{ 0xf0,0x34,0} }, { { 0x33,0},{ 0xf0,0x33,0} }, /*020*/ - { { 0x3B,0},{ 0xf0,0x3B,0} }, { { 0x42,0},{ 0xf0,0x42,0} }, { { 0x4B,0},{ 0xf0,0x4B,0} }, { { 0x4C,0},{ 0xf0,0x4C,0} }, /*024*/ - { { 0x52,0},{ 0xf0,0x52,0} }, { { 0x0E,0},{ 0xf0,0x0E,0} }, { { 0x12,0},{ 0xf0,0x12,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, /*028*/ - { { 0x1A,0},{ 0xf0,0x1A,0} }, { { 0x22,0},{ 0xf0,0x22,0} }, { { 0x21,0},{ 0xf0,0x21,0} }, { { 0x2A,0},{ 0xf0,0x2A,0} }, /*02c*/ - { { 0x32,0},{ 0xf0,0x32,0} }, { { 0x31,0},{ 0xf0,0x31,0} }, { { 0x3A,0},{ 0xf0,0x3A,0} }, { { 0x41,0},{ 0xf0,0x41,0} }, /*030*/ - { { 0x49,0},{ 0xf0,0x49,0} }, { { 0x4A,0},{ 0xf0,0x4A,0} }, { { 0x59,0},{ 0xf0,0x59,0} }, { { 0x7E,0},{ 0xf0,0x7E,0} }, /*034*/ - { { 0x19,0},{ 0xf0,0x19,0} }, { { 0x29,0},{ 0xf0,0x29,0} }, { { 0x14,0},{ 0xf0,0x14,0} }, { { 0x07,0},{ 0xf0,0x07,0} }, /*038*/ - { { 0x0F,0},{ 0xf0,0x0F,0} }, { { 0x17,0},{ 0xf0,0x17,0} }, { { 0x1F,0},{ 0xf0,0x1F,0} }, { { 0x27,0},{ 0xf0,0x27,0} }, /*03c*/ - { { 0x2F,0},{ 0xf0,0x2F,0} }, { { 0x37,0},{ 0xf0,0x37,0} }, { { 0x3F,0},{ 0xf0,0x3F,0} }, { { 0x47,0},{ 0xf0,0x47,0} }, /*040*/ - { { 0x4F,0},{ 0xf0,0x4F,0} }, { { 0x76,0},{ 0xf0,0x76,0} }, { { 0x5F,0},{ 0xf0,0x5F,0} }, { { 0x6C,0},{ 0xf0,0x6C,0} }, /*044*/ - { { 0x75,0},{ 0xf0,0x75,0} }, { { 0x7D,0},{ 0xf0,0x7D,0} }, { { 0x84,0},{ 0xf0,0x84,0} }, { { 0x6B,0},{ 0xf0,0x6B,0} }, /*048*/ - { { 0x73,0},{ 0xf0,0x73,0} }, { { 0x74,0},{ 0xf0,0x74,0} }, { { 0x7C,0},{ 0xf0,0x7C,0} }, { { 0x69,0},{ 0xf0,0x69,0} }, /*04c*/ - { { 0x72,0},{ 0xf0,0x72,0} }, { { 0x7A,0},{ 0xf0,0x7A,0} }, { { 0x70,0},{ 0xf0,0x70,0} }, { { 0x71,0},{ 0xf0,0x71,0} }, /*050*/ - { { 0x57,0},{ 0xf0,0x57,0} }, { { 0x60,0},{ 0xf0,0x60,0} }, { { 0},{ 0} }, { { 0x56,0},{ 0xf0,0x56,0} }, /*054*/ - { { 0x5E,0},{ 0xf0,0x5E,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*058*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*05c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*060*/ - { { 0},{ 0} }, { { 0x10,0},{ 0xf0,0x10,0} }, { { 0x18,0},{ 0xf0,0x18,0} }, { { 0x20,0},{ 0xf0,0x20,0} }, /*064*/ - { { 0x28,0},{ 0xf0,0x28,0} }, { { 0x30,0},{ 0xf0,0x30,0} }, { { 0x38,0},{ 0xf0,0x38,0} }, { { 0x40,0},{ 0xf0,0x40,0} }, /*068*/ - { { 0x48,0},{ 0xf0,0x48,0} }, { { 0x50,0},{ 0xf0,0x50,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*06c*/ - { { 0x87,0},{ 0xf0,0x87,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0x51,0},{ 0xf0,0x51,0} }, /*070*/ - { { 0x53,0},{ 0xf0,0x53,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, { { 0},{ 0} }, { { 0x62,0},{ 0xf0,0x62,0} }, /*074*/ - { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x85,0} }, /*078*/ - { { 0x68,0},{ 0xf0,0x68,0} }, { { 0x13,0},{ 0xf0,0x13,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*07c*/ - - { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ - { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ - { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ - { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ - { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ - { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ - { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ - { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ - { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ - { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ - { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ - { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ - { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ - { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ - { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ - { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ - { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ - { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ - { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ - { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ - { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ - { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ - { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ - { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ - { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ - { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ - { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ - { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ - { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ - - { { 0x62,0},{ 0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ - { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ - { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ - { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ - { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ - { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ - { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ - { { 0x79,0},{ 0xf0,0x79,0} }, { { 0x58,0},{ 0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ - { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ - { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ - { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { { 0x77,0},{ 0xf0,0x77,0} }, { { 0},{ 0} }, { { 0x57,0},{ 0xf0,0x57,0} }, /*134*/ - { { 0x39,0},{ 0xf0,0x39,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ - { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ - { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ - { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { { 0x6E,0},{ 0xf0,0x6E,0} }, /*144*/ - { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x6F,0},{ 0xf0,0x6F,0} }, { { 0},{ 0} }, { { 0x61,0},{ 0xf0,0x61,0} }, /*148*/ - { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { { 0x6A,0},{ 0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { { 0x65,0},{ 0xf0,0x65,0} }, /*14c*/ - { { 0x60,0},{ 0xf0,0x60,0} }, { { 0x6D,0},{ 0xf0,0x6D,0} }, { { 0x67,0},{ 0xf0,0x67,0} }, { { 0x64,0},{ 0xf0,0x64,0} }, /*150*/ - { { 0xd4,0},{ 0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ - { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { { 0x8B,0},{ 0xf0,0x8B,0} }, /*158*/ - { { 0x8C,0},{ 0xf0,0x8C,0} }, { { 0x8D,0},{ 0xf0,0x8D,0} }, { { 0},{ 0} }, { { 0x7F,0},{ 0xf0,0x7F,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { { 0},{ 0} }, /*160*/ - { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ - { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ - { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ - { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ - { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ - { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x08, 0 }, .brk = { 0xf0, 0x08, 0 } }, /* 001 */ + { .mk = { 0x16, 0 }, .brk = { 0xf0, 0x16, 0 } }, /* 002 */ + { .mk = { 0x1E, 0 }, .brk = { 0xf0, 0x1E, 0 } }, /* 003 */ + { .mk = { 0x26, 0 }, .brk = { 0xf0, 0x26, 0 } }, /* 004 */ + { .mk = { 0x25, 0 }, .brk = { 0xf0, 0x25, 0 } }, /* 005 */ + { .mk = { 0x2E, 0 }, .brk = { 0xf0, 0x2E, 0 } }, /* 006 */ + { .mk = { 0x36, 0 }, .brk = { 0xf0, 0x36, 0 } }, /* 007 */ + { .mk = { 0x3D, 0 }, .brk = { 0xf0, 0x3D, 0 } }, /* 008 */ + { .mk = { 0x3E, 0 }, .brk = { 0xf0, 0x3E, 0 } }, /* 009 */ + { .mk = { 0x46, 0 }, .brk = { 0xf0, 0x46, 0 } }, /* 00a */ + { .mk = { 0x45, 0 }, .brk = { 0xf0, 0x45, 0 } }, /* 00b */ + { .mk = { 0x4E, 0 }, .brk = { 0xf0, 0x4E, 0 } }, /* 00c */ + { .mk = { 0x55, 0 }, .brk = { 0xf0, 0x55, 0 } }, /* 00d */ + { .mk = { 0x66, 0 }, .brk = { 0xf0, 0x66, 0 } }, /* 00e */ + { .mk = { 0x0D, 0 }, .brk = { 0xf0, 0x0D, 0 } }, /* 00f */ + { .mk = { 0x15, 0 }, .brk = { 0xf0, 0x15, 0 } }, /* 010 */ + { .mk = { 0x1D, 0 }, .brk = { 0xf0, 0x1D, 0 } }, /* 011 */ + { .mk = { 0x24, 0 }, .brk = { 0xf0, 0x24, 0 } }, /* 012 */ + { .mk = { 0x2D, 0 }, .brk = { 0xf0, 0x2D, 0 } }, /* 013 */ + { .mk = { 0x2C, 0 }, .brk = { 0xf0, 0x2C, 0 } }, /* 014 */ + { .mk = { 0x35, 0 }, .brk = { 0xf0, 0x35, 0 } }, /* 015 */ + { .mk = { 0x3C, 0 }, .brk = { 0xf0, 0x3C, 0 } }, /* 016 */ + { .mk = { 0x43, 0 }, .brk = { 0xf0, 0x43, 0 } }, /* 017 */ + { .mk = { 0x44, 0 }, .brk = { 0xf0, 0x44, 0 } }, /* 018 */ + { .mk = { 0x4D, 0 }, .brk = { 0xf0, 0x4D, 0 } }, /* 019 */ + { .mk = { 0x54, 0 }, .brk = { 0xf0, 0x54, 0 } }, /* 01a */ + { .mk = { 0x5B, 0 }, .brk = { 0xf0, 0x5B, 0 } }, /* 01b */ + { .mk = { 0x5A, 0 }, .brk = { 0xf0, 0x5A, 0 } }, /* 01c */ + { .mk = { 0x11, 0 }, .brk = { 0xf0, 0x11, 0 } }, /* 01d */ + { .mk = { 0x1C, 0 }, .brk = { 0xf0, 0x1C, 0 } }, /* 01e */ + { .mk = { 0x1B, 0 }, .brk = { 0xf0, 0x1B, 0 } }, /* 01f */ + { .mk = { 0x23, 0 }, .brk = { 0xf0, 0x23, 0 } }, /* 020 */ + { .mk = { 0x2B, 0 }, .brk = { 0xf0, 0x2B, 0 } }, /* 021 */ + { .mk = { 0x34, 0 }, .brk = { 0xf0, 0x34, 0 } }, /* 022 */ + { .mk = { 0x33, 0 }, .brk = { 0xf0, 0x33, 0 } }, /* 023 */ + { .mk = { 0x3B, 0 }, .brk = { 0xf0, 0x3B, 0 } }, /* 024 */ + { .mk = { 0x42, 0 }, .brk = { 0xf0, 0x42, 0 } }, /* 025 */ + { .mk = { 0x4B, 0 }, .brk = { 0xf0, 0x4B, 0 } }, /* 026 */ + { .mk = { 0x4C, 0 }, .brk = { 0xf0, 0x4C, 0 } }, /* 027 */ + { .mk = { 0x52, 0 }, .brk = { 0xf0, 0x52, 0 } }, /* 028 */ + { .mk = { 0x0E, 0 }, .brk = { 0xf0, 0x0E, 0 } }, /* 029 */ + { .mk = { 0x12, 0 }, .brk = { 0xf0, 0x12, 0 } }, /* 02a */ + { .mk = { 0x5C, 0 }, .brk = { 0xf0, 0x5C, 0 } }, /* 02b */ + { .mk = { 0x1A, 0 }, .brk = { 0xf0, 0x1A, 0 } }, /* 02c */ + { .mk = { 0x22, 0 }, .brk = { 0xf0, 0x22, 0 } }, /* 02d */ + { .mk = { 0x21, 0 }, .brk = { 0xf0, 0x21, 0 } }, /* 02e */ + { .mk = { 0x2A, 0 }, .brk = { 0xf0, 0x2A, 0 } }, /* 02f */ + { .mk = { 0x32, 0 }, .brk = { 0xf0, 0x32, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xf0, 0x31, 0 } }, /* 031 */ + { .mk = { 0x3A, 0 }, .brk = { 0xf0, 0x3A, 0 } }, /* 032 */ + { .mk = { 0x41, 0 }, .brk = { 0xf0, 0x41, 0 } }, /* 033 */ + { .mk = { 0x49, 0 }, .brk = { 0xf0, 0x49, 0 } }, /* 034 */ + { .mk = { 0x4A, 0 }, .brk = { 0xf0, 0x4A, 0 } }, /* 035 */ + { .mk = { 0x59, 0 }, .brk = { 0xf0, 0x59, 0 } }, /* 036 */ + { .mk = { 0x7E, 0 }, .brk = { 0xf0, 0x7E, 0 } }, /* 037 */ + { .mk = { 0x19, 0 }, .brk = { 0xf0, 0x19, 0 } }, /* 038 */ + { .mk = { 0x29, 0 }, .brk = { 0xf0, 0x29, 0 } }, /* 039 */ + { .mk = { 0x14, 0 }, .brk = { 0xf0, 0x14, 0 } }, /* 03a */ + { .mk = { 0x07, 0 }, .brk = { 0xf0, 0x07, 0 } }, /* 03b */ + { .mk = { 0x0F, 0 }, .brk = { 0xf0, 0x0F, 0 } }, /* 03c */ + { .mk = { 0x17, 0 }, .brk = { 0xf0, 0x17, 0 } }, /* 03d */ + { .mk = { 0x1F, 0 }, .brk = { 0xf0, 0x1F, 0 } }, /* 03e */ + { .mk = { 0x27, 0 }, .brk = { 0xf0, 0x27, 0 } }, /* 03f */ + { .mk = { 0x2F, 0 }, .brk = { 0xf0, 0x2F, 0 } }, /* 040 */ + { .mk = { 0x37, 0 }, .brk = { 0xf0, 0x37, 0 } }, /* 041 */ + { .mk = { 0x3F, 0 }, .brk = { 0xf0, 0x3F, 0 } }, /* 042 */ + { .mk = { 0x47, 0 }, .brk = { 0xf0, 0x47, 0 } }, /* 043 */ + { .mk = { 0x4F, 0 }, .brk = { 0xf0, 0x4F, 0 } }, /* 044 */ + { .mk = { 0x76, 0 }, .brk = { 0xf0, 0x76, 0 } }, /* 045 */ + { .mk = { 0x5F, 0 }, .brk = { 0xf0, 0x5F, 0 } }, /* 046 */ + { .mk = { 0x6C, 0 }, .brk = { 0xf0, 0x6C, 0 } }, /* 047 */ + { .mk = { 0x75, 0 }, .brk = { 0xf0, 0x75, 0 } }, /* 048 */ + { .mk = { 0x7D, 0 }, .brk = { 0xf0, 0x7D, 0 } }, /* 049 */ + { .mk = { 0x84, 0 }, .brk = { 0xf0, 0x84, 0 } }, /* 04a */ + { .mk = { 0x6B, 0 }, .brk = { 0xf0, 0x6B, 0 } }, /* 04b */ + { .mk = { 0x73, 0 }, .brk = { 0xf0, 0x73, 0 } }, /* 04c */ + { .mk = { 0x74, 0 }, .brk = { 0xf0, 0x74, 0 } }, /* 04d */ + { .mk = { 0x7C, 0 }, .brk = { 0xf0, 0x7C, 0 } }, /* 04e */ + { .mk = { 0x69, 0 }, .brk = { 0xf0, 0x69, 0 } }, /* 04f */ + { .mk = { 0x72, 0 }, .brk = { 0xf0, 0x72, 0 } }, /* 050 */ + { .mk = { 0x7A, 0 }, .brk = { 0xf0, 0x7A, 0 } }, /* 051 */ + { .mk = { 0x70, 0 }, .brk = { 0xf0, 0x70, 0 } }, /* 052 */ + { .mk = { 0x71, 0 }, .brk = { 0xf0, 0x71, 0 } }, /* 053 */ + { .mk = { 0x57, 0 }, .brk = { 0xf0, 0x57, 0 } }, /* 054 */ + { .mk = { 0x60, 0 }, .brk = { 0xf0, 0x60, 0 } }, /* 055 */ + { .mk = { 0 }, .brk = { 0 } }, /* 056 */ + { .mk = { 0x56, 0 }, .brk = { 0xf0, 0x56, 0 } }, /* 057 */ + { .mk = { 0x5E, 0 }, .brk = { 0xf0, 0x5E, 0 } }, /* 058 */ + { .mk = { 0 }, .brk = { 0 } }, /* 059 */ + { .mk = { 0 }, .brk = { 0 } }, /* 05a */ + { .mk = { 0 }, .brk = { 0 } }, /* 05b */ + { .mk = { 0 }, .brk = { 0 } }, /* 05c */ + { .mk = { 0 }, .brk = { 0 } }, /* 05d */ + { .mk = { 0 }, .brk = { 0 } }, /* 05e */ + { .mk = { 0 }, .brk = { 0 } }, /* 05f */ + { .mk = { 0 }, .brk = { 0 } }, /* 060 */ + { .mk = { 0 }, .brk = { 0 } }, /* 061 */ + { .mk = { 0 }, .brk = { 0 } }, /* 062 */ + { .mk = { 0 }, .brk = { 0 } }, /* 063 */ + { .mk = { 0 }, .brk = { 0 } }, /* 064 */ + { .mk = { 0x10, 0 }, .brk = { 0xf0, 0x10, 0 } }, /* 065 */ + { .mk = { 0x18, 0 }, .brk = { 0xf0, 0x18, 0 } }, /* 066 */ + { .mk = { 0x20, 0 }, .brk = { 0xf0, 0x20, 0 } }, /* 067 */ + { .mk = { 0x28, 0 }, .brk = { 0xf0, 0x28, 0 } }, /* 068 */ + { .mk = { 0x30, 0 }, .brk = { 0xf0, 0x30, 0 } }, /* 069 */ + { .mk = { 0x38, 0 }, .brk = { 0xf0, 0x38, 0 } }, /* 06a */ + { .mk = { 0x40, 0 }, .brk = { 0xf0, 0x40, 0 } }, /* 06b */ + { .mk = { 0x48, 0 }, .brk = { 0xf0, 0x48, 0 } }, /* 06c */ + { .mk = { 0x50, 0 }, .brk = { 0xf0, 0x50, 0 } }, /* 06d */ + { .mk = { 0 }, .brk = { 0 } }, /* 06e */ + { .mk = { 0 }, .brk = { 0 } }, /* 06f */ + { .mk = { 0x87, 0 }, .brk = { 0xf0, 0x87, 0 } }, /* 070 */ + { .mk = { 0 }, .brk = { 0 } }, /* 071 */ + { .mk = { 0 }, .brk = { 0 } }, /* 072 */ + { .mk = { 0x51, 0 }, .brk = { 0xf0, 0x51, 0 } }, /* 073 */ + { .mk = { 0x53, 0 }, .brk = { 0xf0, 0x53, 0 } }, /* 074 */ + { .mk = { 0x5C, 0 }, .brk = { 0xf0, 0x5C, 0 } }, /* 075 */ + { .mk = { 0 }, .brk = { 0 } }, /* 076 */ + { .mk = { 0x62, 0 }, .brk = { 0xf0, 0x62, 0 } }, /* 077 */ + { .mk = { 0x63, 0 }, .brk = { 0xf0, 0x63, 0 } }, /* 078 */ + { .mk = { 0x86, 0 }, .brk = { 0xf0, 0x86, 0 } }, /* 079 */ + { .mk = { 0 }, .brk = { 0 } }, /* 07a */ + { .mk = { 0x85, 0 }, .brk = { 0xf0, 0x85, 0 } }, /* 07b */ + { .mk = { 0x68, 0 }, .brk = { 0xf0, 0x68, 0 } }, /* 07c */ + { .mk = { 0x13, 0 }, .brk = { 0xf0, 0x13, 0 } }, /* 07d */ + { .mk = { 0 }, .brk = { 0 } }, /* 07e */ + { .mk = { 0 }, .brk = { 0 } }, /* 07f */ + { .mk = { 0x80, 0 }, .brk = { 0xf0, 0x80, 0 } }, /* 080 */ + { .mk = { 0x81, 0 }, .brk = { 0xf0, 0x81, 0 } }, /* 081 */ + { .mk = { 0x82, 0 }, .brk = { 0xf0, 0x82, 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0x85, 0 }, .brk = { 0xf0, 0x54, 0 } }, /* 085 */ + { .mk = { 0x86, 0 }, .brk = { 0xf0, 0x86, 0 } }, /* 086 */ + { .mk = { 0x87, 0 }, .brk = { 0xf0, 0x87, 0 } }, /* 087 */ + { .mk = { 0x88, 0 }, .brk = { 0xf0, 0x88, 0 } }, /* 087 */ + { .mk = { 0x89, 0 }, .brk = { 0xf0, 0x89, 0 } }, /* 088 */ + { .mk = { 0x8a, 0 }, .brk = { 0xf0, 0x8a, 0 } }, /* 089 */ + { .mk = { 0x8b, 0 }, .brk = { 0xf0, 0x8b, 0 } }, /* 08b */ + { .mk = { 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0x8e, 0 }, .brk = { 0xf0, 0x8e, 0 } }, /* 08e */ + { .mk = { 0x8f, 0 }, .brk = { 0xf0, 0x8f, 0 } }, /* 08f */ + { .mk = { 0x90, 0 }, .brk = { 0xf0, 0x90, 0 } }, /* 090 */ + { .mk = { 0x91, 0 }, .brk = { 0xf0, 0x91, 0 } }, /* 091 */ + { .mk = { 0x92, 0 }, .brk = { 0xf0, 0x92, 0 } }, /* 092 */ + { .mk = { 0x93, 0 }, .brk = { 0xf0, 0x93, 0 } }, /* 093 */ + { .mk = { 0x94, 0 }, .brk = { 0xf0, 0x94, 0 } }, /* 094 */ + { .mk = { 0x95, 0 }, .brk = { 0xf0, 0x95, 0 } }, /* 095 */ + { .mk = { 0x96, 0 }, .brk = { 0xf0, 0x96, 0 } }, /* 096 */ + { .mk = { 0x97, 0 }, .brk = { 0xf0, 0x97, 0 } }, /* 097 */ + { .mk = { 0x98, 0 }, .brk = { 0xf0, 0x98, 0 } }, /* 098 */ + { .mk = { 0x99, 0 }, .brk = { 0xf0, 0x99, 0 } }, /* 099 */ + { .mk = { 0x9a, 0 }, .brk = { 0xf0, 0x9a, 0 } }, /* 09a */ + { .mk = { 0x9b, 0 }, .brk = { 0xf0, 0x9b, 0 } }, /* 09b */ + { .mk = { 0x9c, 0 }, .brk = { 0xf0, 0x9c, 0 } }, /* 09c */ + { .mk = { 0x9d, 0 }, .brk = { 0xf0, 0x9d, 0 } }, /* 09d */ + { .mk = { 0x9e, 0 }, .brk = { 0xf0, 0x9e, 0 } }, /* 09e */ + { .mk = { 0x9f, 0 }, .brk = { 0xf0, 0x9f, 0 } }, /* 09f */ + { .mk = { 0xa0, 0 }, .brk = { 0xf0, 0xa0, 0 } }, /* 0a0 */ + { .mk = { 0xa1, 0 }, .brk = { 0xf0, 0xa1, 0 } }, /* 0a1 */ + { .mk = { 0xa2, 0 }, .brk = { 0xf0, 0xa2, 0 } }, /* 0a2 */ + { .mk = { 0xa3, 0 }, .brk = { 0xf0, 0xa3, 0 } }, /* 0a3 */ + { .mk = { 0xa4, 0 }, .brk = { 0xf0, 0xa4, 0 } }, /* 0a4 */ + { .mk = { 0xa5, 0 }, .brk = { 0xf0, 0xa5, 0 } }, /* 0a5 */ + { .mk = { 0xa6, 0 }, .brk = { 0xf0, 0xa6, 0 } }, /* 0a6 */ + { .mk = { 0xa7, 0 }, .brk = { 0xf0, 0xa7, 0 } }, /* 0a7 */ + { .mk = { 0xa8, 0 }, .brk = { 0xf0, 0xa8, 0 } }, /* 0a8 */ + { .mk = { 0xa9, 0 }, .brk = { 0xf0, 0xa9, 0 } }, /* 0a9 */ + { .mk = { 0xaa, 0 }, .brk = { 0xf0, 0xaa, 0 } }, /* 0aa */ + { .mk = { 0xab, 0 }, .brk = { 0xf0, 0xab, 0 } }, /* 0ab */ + { .mk = { 0xac, 0 }, .brk = { 0xf0, 0xac, 0 } }, /* 0ac */ + { .mk = { 0xad, 0 }, .brk = { 0xf0, 0xad, 0 } }, /* 0ad */ + { .mk = { 0xae, 0 }, .brk = { 0xf0, 0xae, 0 } }, /* 0ae */ + { .mk = { 0xaf, 0 }, .brk = { 0xf0, 0xaf, 0 } }, /* 0af */ + { .mk = { 0xb0, 0 }, .brk = { 0xf0, 0xb0, 0 } }, /* 0b0 */ + { .mk = { 0xb1, 0 }, .brk = { 0xf0, 0xb1, 0 } }, /* 0b1 */ + { .mk = { 0xb2, 0 }, .brk = { 0xf0, 0xb2, 0 } }, /* 0b2 */ + { .mk = { 0xb3, 0 }, .brk = { 0xf0, 0xb3, 0 } }, /* 0b3 */ + { .mk = { 0xb4, 0 }, .brk = { 0xf0, 0xb4, 0 } }, /* 0b4 */ + { .mk = { 0xb5, 0 }, .brk = { 0xf0, 0xb5, 0 } }, /* 0b5 */ + { .mk = { 0xb6, 0 }, .brk = { 0xf0, 0xb6, 0 } }, /* 0b6 */ + { .mk = { 0xb7, 0 }, .brk = { 0xf0, 0xb7, 0 } }, /* 0b7 */ + { .mk = { 0xb8, 0 }, .brk = { 0xf0, 0xb8, 0 } }, /* 0b8 */ + { .mk = { 0xb9, 0 }, .brk = { 0xf0, 0xb9, 0 } }, /* 0b9 */ + { .mk = { 0xba, 0 }, .brk = { 0xf0, 0xba, 0 } }, /* 0ba */ + { .mk = { 0xbb, 0 }, .brk = { 0xf0, 0xbb, 0 } }, /* 0bb */ + { .mk = { 0xbc, 0 }, .brk = { 0xf0, 0xbc, 0 } }, /* 0bc */ + { .mk = { 0xbd, 0 }, .brk = { 0xf0, 0xbd, 0 } }, /* 0bd */ + { .mk = { 0xbe, 0 }, .brk = { 0xf0, 0xbe, 0 } }, /* 0be */ + { .mk = { 0xbf, 0 }, .brk = { 0xf0, 0xbf, 0 } }, /* 0bf */ + { .mk = { 0xc0, 0 }, .brk = { 0xf0, 0xc0, 0 } }, /* 0c0 */ + { .mk = { 0xc1, 0 }, .brk = { 0xf0, 0xc1, 0 } }, /* 0c1 */ + { .mk = { 0xc2, 0 }, .brk = { 0xf0, 0xc2, 0 } }, /* 0c2 */ + { .mk = { 0xc3, 0 }, .brk = { 0xf0, 0xc3, 0 } }, /* 0c3 */ + { .mk = { 0xc4, 0 }, .brk = { 0xf0, 0xc4, 0 } }, /* 0c4 */ + { .mk = { 0xc5, 0 }, .brk = { 0xf0, 0xc5, 0 } }, /* 0c5 */ + { .mk = { 0xc6, 0 }, .brk = { 0xf0, 0xc6, 0 } }, /* 0c6 */ + { .mk = { 0xc7, 0 }, .brk = { 0xf0, 0xc7, 0 } }, /* 0c7 */ + { .mk = { 0xc8, 0 }, .brk = { 0xf0, 0xc8, 0 } }, /* 0c8 */ + { .mk = { 0xc9, 0 }, .brk = { 0xf0, 0xc9, 0 } }, /* 0c9 */ + { .mk = { 0xca, 0 }, .brk = { 0xf0, 0xca, 0 } }, /* 0ca */ + { .mk = { 0xcb, 0 }, .brk = { 0xf0, 0xcb, 0 } }, /* 0cb */ + { .mk = { 0xcc, 0 }, .brk = { 0xf0, 0xcc, 0 } }, /* 0cc */ + { .mk = { 0xcd, 0 }, .brk = { 0xf0, 0xcd, 0 } }, /* 0cd */ + { .mk = { 0xce, 0 }, .brk = { 0xf0, 0xce, 0 } }, /* 0ce */ + { .mk = { 0xcf, 0 }, .brk = { 0xf0, 0xcf, 0 } }, /* 0cf */ + { .mk = { 0xd0, 0 }, .brk = { 0xf0, 0xd0, 0 } }, /* 0d0 */ + { .mk = { 0xd1, 0 }, .brk = { 0xf0, 0xd0, 0 } }, /* 0d1 */ + { .mk = { 0xd2, 0 }, .brk = { 0xf0, 0xd2, 0 } }, /* 0d2 */ + { .mk = { 0xd3, 0 }, .brk = { 0xf0, 0xd3, 0 } }, /* 0d3 */ + { .mk = { 0xd4, 0 }, .brk = { 0xf0, 0xd4, 0 } }, /* 0d4 */ + { .mk = { 0xd5, 0 }, .brk = { 0xf0, 0xd5, 0 } }, /* 0d5 */ + { .mk = { 0xd6, 0 }, .brk = { 0xf0, 0xd6, 0 } }, /* 0d6 */ + { .mk = { 0xd7, 0 }, .brk = { 0xf0, 0xd7, 0 } }, /* 0d7 */ + { .mk = { 0xd8, 0 }, .brk = { 0xf0, 0xd8, 0 } }, /* 0d8 */ + { .mk = { 0xd9, 0 }, .brk = { 0xf0, 0xd9, 0 } }, /* 0d9 */ + { .mk = { 0xda, 0 }, .brk = { 0xf0, 0xda, 0 } }, /* 0da */ + { .mk = { 0xdb, 0 }, .brk = { 0xf0, 0xdb, 0 } }, /* 0db */ + { .mk = { 0xdc, 0 }, .brk = { 0xf0, 0xdc, 0 } }, /* 0dc */ + { .mk = { 0xdd, 0 }, .brk = { 0xf0, 0xdd, 0 } }, /* 0dd */ + { .mk = { 0xde, 0 }, .brk = { 0xf0, 0xde, 0 } }, /* 0de */ + { .mk = { 0xdf, 0 }, .brk = { 0xf0, 0xdf, 0 } }, /* 0df */ + { .mk = { 0xe0, 0 }, .brk = { 0xf0, 0xe0, 0 } }, /* 0e0 */ + { .mk = { 0xe1, 0 }, .brk = { 0xf0, 0xe1, 0 } }, /* 0e1 */ + { .mk = { 0xe2, 0 }, .brk = { 0xf0, 0xe2, 0 } }, /* 0e2 */ + { .mk = { 0xe3, 0 }, .brk = { 0xf0, 0xe3, 0 } }, /* 0e3 */ + { .mk = { 0xe4, 0 }, .brk = { 0xf0, 0xe4, 0 } }, /* 0e4 */ + { .mk = { 0xe5, 0 }, .brk = { 0xf0, 0xe5, 0 } }, /* 0e5 */ + { .mk = { 0xe6, 0 }, .brk = { 0xf0, 0xe6, 0 } }, /* 0e6 */ + { .mk = { 0xe7, 0 }, .brk = { 0xf0, 0xe7, 0 } }, /* 0e7 */ + { .mk = { 0xe8, 0 }, .brk = { 0xf0, 0xe8, 0 } }, /* 0e7 */ + { .mk = { 0xe9, 0 }, .brk = { 0xf0, 0xe9, 0 } }, /* 0e8 */ + { .mk = { 0xea, 0 }, .brk = { 0xf0, 0xea, 0 } }, /* 0e9 */ + { .mk = { 0xeb, 0 }, .brk = { 0xf0, 0xeb, 0 } }, /* 0eb */ + { .mk = { 0xec, 0 }, .brk = { 0xf0, 0xec, 0 } }, /* 0ec */ + { .mk = { 0xed, 0 }, .brk = { 0xf0, 0xed, 0 } }, /* 0ed */ + { .mk = { 0xee, 0 }, .brk = { 0xf0, 0xee, 0 } }, /* 0ee */ + { .mk = { 0xef, 0 }, .brk = { 0xf0, 0xef, 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0xf1, 0 }, .brk = { 0xf0, 0xf1, 0 } }, /* 0f1 */ + { .mk = { 0xf2, 0 }, .brk = { 0xf0, 0xf2, 0 } }, /* 0f2 */ + { .mk = { 0xf3, 0 }, .brk = { 0xf0, 0xf3, 0 } }, /* 0f3 */ + { .mk = { 0xf4, 0 }, .brk = { 0xf0, 0xf4, 0 } }, /* 0f4 */ + { .mk = { 0xf5, 0 }, .brk = { 0xf0, 0xf5, 0 } }, /* 0f5 */ + { .mk = { 0xf6, 0 }, .brk = { 0xf0, 0xf6, 0 } }, /* 0f6 */ + { .mk = { 0xf7, 0 }, .brk = { 0xf0, 0xf7, 0 } }, /* 0f7 */ + { .mk = { 0xf8, 0 }, .brk = { 0xf0, 0xf8, 0 } }, /* 0f8 */ + { .mk = { 0xf9, 0 }, .brk = { 0xf0, 0xf9, 0 } }, /* 0f9 */ + { .mk = { 0xfa, 0 }, .brk = { 0xf0, 0xfa, 0 } }, /* 0fa */ + { .mk = { 0xfb, 0 }, .brk = { 0xf0, 0xfb, 0 } }, /* 0fb */ + { .mk = { 0xfc, 0 }, .brk = { 0xf0, 0xfc, 0 } }, /* 0fc */ + { .mk = { 0xfd, 0 }, .brk = { 0xf0, 0xfd, 0 } }, /* 0fd */ + { .mk = { 0xfe, 0 }, .brk = { 0xf0, 0xfe, 0 } }, /* 0fe */ + { .mk = { 0xff, 0 }, .brk = { 0xf0, 0xff, 0 } }, /* 0ff */ + { .mk = { 0x62, 0 }, .brk = { 0xF0, 0x62, 0 } }, /* 100 */ + { .mk = {0xe0, 0x76, 0 }, .brk = { 0xe0, 0xF0, 0x76, 0 } }, /* 101 */ + { .mk = {0xe0, 0x16, 0 }, .brk = { 0xe0, 0xF0, 0x16, 0 } }, /* 102 */ + { .mk = {0xe0, 0x1E, 0 }, .brk = { 0xe0, 0xF0, 0x1E, 0 } }, /* 103 */ + { .mk = {0xe0, 0x26, 0 }, .brk = { 0xe0, 0xF0, 0x26, 0 } }, /* 104 */ + { .mk = {0xe0, 0x25, 0 }, .brk = { 0xe0, 0xF0, 0x25, 0 } }, /* 105 */ + { .mk = {0xe0, 0x2E, 0 }, .brk = { 0xe0, 0xF0, 0x2E, 0 } }, /* 106 */ + { .mk = {0xe0, 0x36, 0 }, .brk = { 0xe0, 0xF0, 0x36, 0 } }, /* 107 */ + { .mk = {0xe0, 0x3D, 0 }, .brk = { 0xe0, 0xF0, 0x3D, 0 } }, /* 108 */ + { .mk = {0xe0, 0x3E, 0 }, .brk = { 0xe0, 0xF0, 0x3E, 0 } }, /* 109 */ + { .mk = {0xe0, 0x46, 0 }, .brk = { 0xe0, 0xF0, 0x46, 0 } }, /* 10a */ + { .mk = {0xe0, 0x45, 0 }, .brk = { 0xe0, 0xF0, 0x45, 0 } }, /* 10b */ + { .mk = {0xe0, 0x4E, 0 }, .brk = { 0xe0, 0xF0, 0x4E, 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = {0xe0, 0x66, 0 }, .brk = { 0xe0, 0xF0, 0x66, 0 } }, /* 10e */ + { .mk = {0xe0, 0x0D, 0 }, .brk = { 0xe0, 0xF0, 0x0D, 0 } }, /* 10f */ + { .mk = {0xe0, 0x15, 0 }, .brk = { 0xe0, 0xF0, 0x15, 0 } }, /* 110 */ + { .mk = {0xe0, 0x1D, 0 }, .brk = { 0xe0, 0xF0, 0x1D, 0 } }, /* 111 */ + { .mk = {0xe0, 0x24, 0 }, .brk = { 0xe0, 0xF0, 0x24, 0 } }, /* 112 */ + { .mk = {0xe0, 0x2D, 0 }, .brk = { 0xe0, 0xF0, 0x2D, 0 } }, /* 113 */ + { .mk = {0xe0, 0x2C, 0 }, .brk = { 0xe0, 0xF0, 0x2C, 0 } }, /* 114 */ + { .mk = {0xe0, 0x35, 0 }, .brk = { 0xe0, 0xF0, 0x35, 0 } }, /* 115 */ + { .mk = {0xe0, 0x3C, 0 }, .brk = { 0xe0, 0xF0, 0x3C, 0 } }, /* 116 */ + { .mk = {0xe0, 0x43, 0 }, .brk = { 0xe0, 0xF0, 0x43, 0 } }, /* 117 */ + { .mk = {0xe0, 0x44, 0 }, .brk = { 0xe0, 0xF0, 0x44, 0 } }, /* 118 */ + { .mk = {0xe0, 0x4D, 0 }, .brk = { 0xe0, 0xF0, 0x4D, 0 } }, /* 119 */ + { .mk = {0xe0, 0x54, 0 }, .brk = { 0xe0, 0xF0, 0x54, 0 } }, /* 11a */ + { .mk = {0xe0, 0x5B, 0 }, .brk = { 0xe0, 0xF0, 0x5B, 0 } }, /* 11b */ + { .mk = { 0x79, 0 }, .brk = { 0xf0, 0x79, 0 } }, /* 11c */ + { .mk = { 0x58, 0 }, .brk = { 0xf0, 0x58, 0 } }, /* 11d */ + { .mk = {0xe0, 0x1C, 0 }, .brk = { 0xe0, 0xF0, 0x1C, 0 } }, /* 11e */ + { .mk = {0xe0, 0x1B, 0 }, .brk = { 0xe0, 0xF0, 0x1B, 0 } }, /* 11f */ + { .mk = {0xe0, 0x23, 0 }, .brk = { 0xe0, 0xF0, 0x23, 0 } }, /* 120 */ + { .mk = {0xe0, 0x2B, 0 }, .brk = { 0xe0, 0xF0, 0x2B, 0 } }, /* 121 */ + { .mk = {0xe0, 0x34, 0 }, .brk = { 0xe0, 0xF0, 0x34, 0 } }, /* 122 */ + { .mk = {0xe0, 0x33, 0 }, .brk = { 0xe0, 0xF0, 0x33, 0 } }, /* 123 */ + { .mk = {0xe0, 0x3B, 0 }, .brk = { 0xe0, 0xF0, 0x3B, 0 } }, /* 124 */ + { .mk = {0xe0, 0x42, 0 }, .brk = { 0xe0, 0xF0, 0x42, 0 } }, /* 125 */ + { .mk = {0xe0, 0x4B, 0 }, .brk = { 0xe0, 0xF0, 0x4B, 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = {0xe0, 0x1A, 0 }, .brk = { 0xe0, 0xF0, 0x1A, 0 } }, /* 12c */ + { .mk = {0xe0, 0x22, 0 }, .brk = { 0xe0, 0xF0, 0x22, 0 } }, /* 12d */ + { .mk = {0xe0, 0x21, 0 }, .brk = { 0xe0, 0xF0, 0x21, 0 } }, /* 12e */ + { .mk = {0xe0, 0x2A, 0 }, .brk = { 0xe0, 0xF0, 0x2A, 0 } }, /* 12f */ + { .mk = {0xe0, 0x32, 0 }, .brk = { 0xe0, 0xF0, 0x32, 0 } }, /* 130 */ + { .mk = {0xe0, 0x31, 0 }, .brk = { 0xe0, 0xF0, 0x31, 0 } }, /* 131 */ + { .mk = {0xe0, 0x3A, 0 }, .brk = { 0xe0, 0xF0, 0x3A, 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = {0xe0, 0x49, 0 }, .brk = { 0xe0, 0xF0, 0x49, 0 } }, /* 134 */ + { .mk = { 0x77, 0 }, .brk = { 0xf0, 0x77, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = { 0x57, 0 }, .brk = { 0xf0, 0x57, 0 } }, /* 137 */ + { .mk = { 0x39, 0 }, .brk = { 0xf0, 0x39, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xF0, 0x58, 0 } }, /* 13a */ + { .mk = {0xe0, 0x05, 0 }, .brk = { 0xe0, 0xF0, 0x05, 0 } }, /* 13b */ + { .mk = {0xe0, 0x06, 0 }, .brk = { 0xe0, 0xF0, 0x06, 0 } }, /* 13c */ + { .mk = {0xe0, 0x04, 0 }, .brk = { 0xe0, 0xF0, 0x04, 0 } }, /* 13d */ + { .mk = {0xe0, 0x0C, 0 }, .brk = { 0xe0, 0xF0, 0x0C, 0 } }, /* 13e */ + { .mk = {0xe0, 0x03, 0 }, .brk = { 0xe0, 0xF0, 0x03, 0 } }, /* 13f */ + { .mk = {0xe0, 0x0B, 0 }, .brk = { 0xe0, 0xF0, 0x0B, 0 } }, /* 140 */ + { .mk = {0xe0, 0x02, 0 }, .brk = { 0xe0, 0xF0, 0x02, 0 } }, /* 141 */ + { .mk = {0xe0, 0x0A, 0 }, .brk = { 0xe0, 0xF0, 0x0A, 0 } }, /* 142 */ + { .mk = {0xe0, 0x01, 0 }, .brk = { 0xe0, 0xF0, 0x01, 0 } }, /* 143 */ + { .mk = {0xe0, 0x09, 0 }, .brk = { 0xe0, 0xF0, 0x09, 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = {0xe0, 0x7E, 0 }, .brk = { 0xe0, 0xF0, 0x7E, 0 } }, /* 146 */ + { .mk = { 0x6E, 0 }, .brk = { 0xf0, 0x6E, 0 } }, /* 147 */ + { .mk = { 0x63, 0 }, .brk = { 0xf0, 0x63, 0 } }, /* 148 */ + { .mk = { 0x6F, 0 }, .brk = { 0xf0, 0x6F, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = { 0x61, 0 }, .brk = { 0xf0, 0x61, 0 } }, /* 14b */ + { .mk = {0xe0, 0x73, 0 }, .brk = { 0xe0, 0xF0, 0x73, 0 } }, /* 14c */ + { .mk = { 0x6A, 0 }, .brk = { 0xf0, 0x6A, 0 } }, /* 14d */ + { .mk = {0xe0, 0x79, 0 }, .brk = { 0xe0, 0xF0, 0x79, 0 } }, /* 14e */ + { .mk = { 0x65, 0 }, .brk = { 0xf0, 0x65, 0 } }, /* 14f */ + { .mk = { 0x60, 0 }, .brk = { 0xf0, 0x60, 0 } }, /* 150 */ + { .mk = { 0x6D, 0 }, .brk = { 0xf0, 0x6D, 0 } }, /* 151 */ + { .mk = { 0x67, 0 }, .brk = { 0xf0, 0x67, 0 } }, /* 152 */ + { .mk = { 0x64, 0 }, .brk = { 0xf0, 0x64, 0 } }, /* 153 */ + { .mk = { 0xd4, 0 }, .brk = { 0xf0, 0xD4, 0 } }, /* 154 */ + { .mk = {0xe0, 0x60, 0 }, .brk = { 0xe0, 0xF0, 0x60, 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = {0xe0, 0x78, 0 }, .brk = { 0xe0, 0xF0, 0x78, 0 } }, /* 157 */ + { .mk = {0xe0, 0x07, 0 }, .brk = { 0xe0, 0xF0, 0x07, 0 } }, /* 158 */ + { .mk = {0xe0, 0x0F, 0 }, .brk = { 0xe0, 0xF0, 0x0F, 0 } }, /* 159 */ + { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0xF0, 0x17, 0 } }, /* 15a */ + { .mk = { 0x8B, 0 }, .brk = { 0xf0, 0x8B, 0 } }, /* 15b */ + { .mk = { 0x8C, 0 }, .brk = { 0xf0, 0x8C, 0 } }, /* 15c */ + { .mk = { 0x8D, 0 }, .brk = { 0xf0, 0x8D, 0 } }, /* 15d */ + { .mk = { 0 }, .brk = { 0 } }, /* 15e */ + { .mk = { 0x7F, 0 }, .brk = { 0xf0, 0x7F, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = {0xe0, 0x4F, 0 }, .brk = { 0xe0, 0xF0, 0x4F, 0 } }, /* 161 */ + { .mk = {0xe0, 0x56, 0 }, .brk = { 0xe0, 0xF0, 0x56, 0 } }, /* 162 */ + { .mk = { 0 }, .brk = { 0 } }, /* 163 */ + { .mk = {0xe0, 0x08, 0 }, .brk = { 0xe0, 0xF0, 0x08, 0 } }, /* 164 */ + { .mk = {0xe0, 0x10, 0 }, .brk = { 0xe0, 0xF0, 0x10, 0 } }, /* 165 */ + { .mk = {0xe0, 0x18, 0 }, .brk = { 0xe0, 0xF0, 0x18, 0 } }, /* 166 */ + { .mk = {0xe0, 0x20, 0 }, .brk = { 0xe0, 0xF0, 0x20, 0 } }, /* 167 */ + { .mk = {0xe0, 0x28, 0 }, .brk = { 0xe0, 0xF0, 0x28, 0 } }, /* 168 */ + { .mk = {0xe0, 0x30, 0 }, .brk = { 0xe0, 0xF0, 0x30, 0 } }, /* 169 */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xF0, 0x38, 0 } }, /* 16a */ + { .mk = {0xe0, 0x40, 0 }, .brk = { 0xe0, 0xF0, 0x40, 0 } }, /* 16b */ + { .mk = {0xe0, 0x48, 0 }, .brk = { 0xe0, 0xF0, 0x48, 0 } }, /* 16c */ + { .mk = {0xe0, 0x50, 0 }, .brk = { 0xe0, 0xF0, 0x50, 0 } }, /* 16d */ + { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xF0, 0x57, 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = {0xe0, 0x13, 0 }, .brk = { 0xe0, 0xF0, 0x13, 0 } }, /* 170 */ + { .mk = {0xe0, 0x19, 0 }, .brk = { 0xe0, 0xF0, 0x19, 0 } }, /* 171 */ + { .mk = {0xe0, 0x39, 0 }, .brk = { 0xe0, 0xF0, 0x39, 0 } }, /* 172 */ + { .mk = {0xe0, 0x51, 0 }, .brk = { 0xe0, 0xF0, 0x51, 0 } }, /* 173 */ + { .mk = {0xe0, 0x53, 0 }, .brk = { 0xe0, 0xF0, 0x53, 0 } }, /* 174 */ + { .mk = {0xe0, 0x5C, 0 }, .brk = { 0xe0, 0xF0, 0x5C, 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = {0xe0, 0x62, 0 }, .brk = { 0xe0, 0xF0, 0x62, 0 } }, /* 177 */ + { .mk = {0xe0, 0x63, 0 }, .brk = { 0xe0, 0xF0, 0x63, 0 } }, /* 178 */ + { .mk = {0xe0, 0x64, 0 }, .brk = { 0xe0, 0xF0, 0x64, 0 } }, /* 179 */ + { .mk = {0xe0, 0x65, 0 }, .brk = { 0xe0, 0xF0, 0x65, 0 } }, /* 17a */ + { .mk = {0xe0, 0x67, 0 }, .brk = { 0xe0, 0xF0, 0x67, 0 } }, /* 17b */ + { .mk = {0xe0, 0x68, 0 }, .brk = { 0xe0, 0xF0, 0x68, 0 } }, /* 17c */ + { .mk = {0xe0, 0x6A, 0 }, .brk = { 0xe0, 0xF0, 0x6A, 0 } }, /* 17d */ + { .mk = {0xe0, 0x6D, 0 }, .brk = { 0xe0, 0xF0, 0x6D, 0 } }, /* 17e */ + { .mk = {0xe0, 0x6E, 0 }, .brk = { 0xe0, 0xF0, 0x6E, 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = {0xe0, 0xe1, 0 }, .brk = { 0xe0, 0xF0, 0xE1, 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = {0xe0, 0xee, 0 }, .brk = { 0xe0, 0xF0, 0xEE, 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = {0xe0, 0xf1, 0 }, .brk = { 0xe0, 0xF0, 0xF1, 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = {0xe0, 0xfe, 0 }, .brk = { 0xe0, 0xF0, 0xFE, 0 } }, /* 1fe */ + { .mk = {0xe0, 0xff, 0 }, .brk = { 0xe0, 0xF0, 0xFF, 0 } } /* 1ff */ // clang-format on }; @@ -947,6 +2102,7 @@ keyboard_at_write(void *priv) /* TODO: This is supposed to resend multiple bytes after some commands. */ case 0xfe: /* resend last scan code */ keyboard_at_log("%s: resend last scan code\n", dev->name); + kbc_at_dev_queue_add(dev, 0xfa, 0); kbc_at_dev_queue_add(dev, dev->last_scan_code, 0); break; @@ -1029,7 +2185,7 @@ static const device_config_t keyboard_at_config[] = { .description = "Type", .type = CONFIG_SELECTION, .default_string = "", - .default_int = 2, + .default_int = 1, .file_filter = "", .spinner = { 0 }, .selection = { diff --git a/src/device/keyboard_xt.c b/src/device/keyboard_xt.c index f65a6dffc7..b90f4a77a3 100644 --- a/src/device/keyboard_xt.c +++ b/src/device/keyboard_xt.c @@ -90,262 +90,518 @@ typedef struct xtkbd_t { /*XT keyboard has no escape scancodes, and no scancodes beyond 53*/ const scancode scancode_xt[512] = { // clang-format off - { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, - { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, - { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, - { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, - { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, - { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, - { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, - { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, - { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, - { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, - { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, - { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, - { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, - { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, - { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, - { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, - { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, - { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, - { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, - { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, - { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, - { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, - { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, - { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, - { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, - { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, - { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, - { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, - { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, - { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, - { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, - { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, - { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, - { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, - { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*054*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*058*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*05c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*060*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*064*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*068*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*06c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*070*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*074*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*078*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*07c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*080*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*084*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*088*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*08c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*090*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*094*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*098*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*09c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0fc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*100*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*104*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*108*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*10c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*110*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*114*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*118*/ - { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0}, {0} }, { {0}, {0} }, /*11c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*120*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*124*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*128*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*12c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*130*/ - { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, - { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ - { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*138*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*13c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*140*/ - { {0}, {0} }, { {0}, {0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ - { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*154*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*158*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*15c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*160*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*164*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*168*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*16c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*170*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*174*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*148*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*17c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*180*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*184*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*88*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*18c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*190*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*194*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*198*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*19c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 012 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0 }, .brk = { 0 } }, /* 054 */ + { .mk = { 0 }, .brk = { 0 } }, /* 055 */ + { .mk = { 0 }, .brk = { 0 } }, /* 056 */ + { .mk = { 0 }, .brk = { 0 } }, /* 057 */ + { .mk = { 0 }, .brk = { 0 } }, /* 058 */ + { .mk = { 0 }, .brk = { 0 } }, /* 059 */ + { .mk = { 0 }, .brk = { 0 } }, /* 05a */ + { .mk = { 0 }, .brk = { 0 } }, /* 05b */ + { .mk = { 0 }, .brk = { 0 } }, /* 05c */ + { .mk = { 0 }, .brk = { 0 } }, /* 05d */ + { .mk = { 0 }, .brk = { 0 } }, /* 05e */ + { .mk = { 0 }, .brk = { 0 } }, /* 05f */ + { .mk = { 0 }, .brk = { 0 } }, /* 060 */ + { .mk = { 0 }, .brk = { 0 } }, /* 061 */ + { .mk = { 0 }, .brk = { 0 } }, /* 062 */ + { .mk = { 0 }, .brk = { 0 } }, /* 063 */ + { .mk = { 0 }, .brk = { 0 } }, /* 064 */ + { .mk = { 0 }, .brk = { 0 } }, /* 065 */ + { .mk = { 0 }, .brk = { 0 } }, /* 066 */ + { .mk = { 0 }, .brk = { 0 } }, /* 067 */ + { .mk = { 0 }, .brk = { 0 } }, /* 068 */ + { .mk = { 0 }, .brk = { 0 } }, /* 069 */ + { .mk = { 0 }, .brk = { 0 } }, /* 06a */ + { .mk = { 0 }, .brk = { 0 } }, /* 06b */ + { .mk = { 0 }, .brk = { 0 } }, /* 06c */ + { .mk = { 0 }, .brk = { 0 } }, /* 06d */ + { .mk = { 0 }, .brk = { 0 } }, /* 06e */ + { .mk = { 0 }, .brk = { 0 } }, /* 06f */ + { .mk = { 0 }, .brk = { 0 } }, /* 070 */ + { .mk = { 0 }, .brk = { 0 } }, /* 071 */ + { .mk = { 0 }, .brk = { 0 } }, /* 072 */ + { .mk = { 0 }, .brk = { 0 } }, /* 073 */ + { .mk = { 0 }, .brk = { 0 } }, /* 074 */ + { .mk = { 0 }, .brk = { 0 } }, /* 075 */ + { .mk = { 0 }, .brk = { 0 } }, /* 076 */ + { .mk = { 0 }, .brk = { 0 } }, /* 077 */ + { .mk = { 0 }, .brk = { 0 } }, /* 078 */ + { .mk = { 0 }, .brk = { 0 } }, /* 079 */ + { .mk = { 0 }, .brk = { 0 } }, /* 07a */ + { .mk = { 0 }, .brk = { 0 } }, /* 07b */ + { .mk = { 0 }, .brk = { 0 } }, /* 07c */ + { .mk = { 0 }, .brk = { 0 } }, /* 07d */ + { .mk = { 0 }, .brk = { 0 } }, /* 07e */ + { .mk = { 0 }, .brk = { 0 } }, /* 07f */ + { .mk = { 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = { 0 }, .brk = { 0 } }, /* 100 */ + { .mk = { 0 }, .brk = { 0 } }, /* 101 */ + { .mk = { 0 }, .brk = { 0 } }, /* 102 */ + { .mk = { 0 }, .brk = { 0 } }, /* 103 */ + { .mk = { 0 }, .brk = { 0 } }, /* 104 */ + { .mk = { 0 }, .brk = { 0 } }, /* 105 */ + { .mk = { 0 }, .brk = { 0 } }, /* 106 */ + { .mk = { 0 }, .brk = { 0 } }, /* 107 */ + { .mk = { 0 }, .brk = { 0 } }, /* 108 */ + { .mk = { 0 }, .brk = { 0 } }, /* 109 */ + { .mk = { 0 }, .brk = { 0 } }, /* 10a */ + { .mk = { 0 }, .brk = { 0 } }, /* 10b */ + { .mk = { 0 }, .brk = { 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = { 0 }, .brk = { 0 } }, /* 10e */ + { .mk = { 0 }, .brk = { 0 } }, /* 10f */ + { .mk = { 0 }, .brk = { 0 } }, /* 110 */ + { .mk = { 0 }, .brk = { 0 } }, /* 111 */ + { .mk = { 0 }, .brk = { 0 } }, /* 112 */ + { .mk = { 0 }, .brk = { 0 } }, /* 113 */ + { .mk = { 0 }, .brk = { 0 } }, /* 114 */ + { .mk = { 0 }, .brk = { 0 } }, /* 115 */ + { .mk = { 0 }, .brk = { 0 } }, /* 116 */ + { .mk = { 0 }, .brk = { 0 } }, /* 117 */ + { .mk = { 0 }, .brk = { 0 } }, /* 118 */ + { .mk = { 0 }, .brk = { 0 } }, /* 119 */ + { .mk = { 0 }, .brk = { 0 } }, /* 11a */ + { .mk = { 0 }, .brk = { 0 } }, /* 11b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 11c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 11d */ + { .mk = { 0 }, .brk = { 0 } }, /* 11e */ + { .mk = { 0 }, .brk = { 0 } }, /* 11f */ + { .mk = { 0 }, .brk = { 0 } }, /* 120 */ + { .mk = { 0 }, .brk = { 0 } }, /* 121 */ + { .mk = { 0 }, .brk = { 0 } }, /* 122 */ + { .mk = { 0 }, .brk = { 0 } }, /* 123 */ + { .mk = { 0 }, .brk = { 0 } }, /* 124 */ + { .mk = { 0 }, .brk = { 0 } }, /* 125 */ + { .mk = { 0 }, .brk = { 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = { 0 }, .brk = { 0 } }, /* 12c */ + { .mk = { 0 }, .brk = { 0 } }, /* 12d */ + { .mk = { 0 }, .brk = { 0 } }, /* 12e */ + { .mk = { 0 }, .brk = { 0 } }, /* 12f */ + { .mk = { 0 }, .brk = { 0 } }, /* 130 */ + { .mk = { 0 }, .brk = { 0 } }, /* 131 */ + { .mk = { 0 }, .brk = { 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = { 0 }, .brk = { 0 } }, /* 134 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 137 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = { 0 }, .brk = { 0 } }, /* 13a */ + { .mk = { 0 }, .brk = { 0 } }, /* 13b */ + { .mk = { 0 }, .brk = { 0 } }, /* 13c */ + { .mk = { 0 }, .brk = { 0 } }, /* 13d */ + { .mk = { 0 }, .brk = { 0 } }, /* 13e */ + { .mk = { 0 }, .brk = { 0 } }, /* 13f */ + { .mk = { 0 }, .brk = { 0 } }, /* 140 */ + { .mk = { 0 }, .brk = { 0 } }, /* 141 */ + { .mk = { 0 }, .brk = { 0 } }, /* 142 */ + { .mk = { 0 }, .brk = { 0 } }, /* 143 */ + { .mk = { 0 }, .brk = { 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 146 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 147 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 148 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 14b */ + { .mk = { 0 }, .brk = { 0 } }, /* 14c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 14d */ + { .mk = { 0 }, .brk = { 0 } }, /* 14e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 14f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 150 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 151 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 152 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = { 0 }, .brk = { 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = { 0 }, .brk = { 0 } }, /* 157 */ + { .mk = { 0 }, .brk = { 0 } }, /* 158 */ + { .mk = { 0 }, .brk = { 0 } }, /* 159 */ + { .mk = { 0 }, .brk = { 0 } }, /* 15a */ + { .mk = { 0 }, .brk = { 0 } }, /* 15b */ + { .mk = { 0 }, .brk = { 0 } }, /* 15c */ + { .mk = { 0 }, .brk = { 0 } }, /* 15d */ + { .mk = { 0 }, .brk = { 0 } }, /* 15e */ + { .mk = { 0 }, .brk = { 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = { 0 }, .brk = { 0 } }, /* 161 */ + { .mk = { 0 }, .brk = { 0 } }, /* 162 */ + { .mk = { 0 }, .brk = { 0 } }, /* 163 */ + { .mk = { 0 }, .brk = { 0 } }, /* 164 */ + { .mk = { 0 }, .brk = { 0 } }, /* 165 */ + { .mk = { 0 }, .brk = { 0 } }, /* 166 */ + { .mk = { 0 }, .brk = { 0 } }, /* 167 */ + { .mk = { 0 }, .brk = { 0 } }, /* 168 */ + { .mk = { 0 }, .brk = { 0 } }, /* 169 */ + { .mk = { 0 }, .brk = { 0 } }, /* 16a */ + { .mk = { 0 }, .brk = { 0 } }, /* 16b */ + { .mk = { 0 }, .brk = { 0 } }, /* 16c */ + { .mk = { 0 }, .brk = { 0 } }, /* 16d */ + { .mk = { 0 }, .brk = { 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = { 0 }, .brk = { 0 } }, /* 170 */ + { .mk = { 0 }, .brk = { 0 } }, /* 171 */ + { .mk = { 0 }, .brk = { 0 } }, /* 172 */ + { .mk = { 0 }, .brk = { 0 } }, /* 173 */ + { .mk = { 0 }, .brk = { 0 } }, /* 174 */ + { .mk = { 0 }, .brk = { 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = { 0 }, .brk = { 0 } }, /* 177 */ + { .mk = { 0 }, .brk = { 0 } }, /* 178 */ + { .mk = { 0 }, .brk = { 0 } }, /* 179 */ + { .mk = { 0 }, .brk = { 0 } }, /* 17a */ + { .mk = { 0 }, .brk = { 0 } }, /* 17b */ + { .mk = { 0 }, .brk = { 0 } }, /* 17c */ + { .mk = { 0 }, .brk = { 0 } }, /* 17d */ + { .mk = { 0 }, .brk = { 0 } }, /* 17e */ + { .mk = { 0 }, .brk = { 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; @@ -672,11 +928,11 @@ kbd_read(uint16_t port, void *priv) else { /* LaserXT = Always 512k RAM; LaserXT/3 = Bit 0: set = 512k, clear = 256k. */ -#if defined(DEV_BRANCH) && defined(USE_LASERXT) +#ifdef USE_LASERXT if (kbd->type == KBD_TYPE_VTECH) ret = ((mem_size == 512) ? 0x0d : 0x0c) | (hasfpu ? 0x02 : 0x00); else -#endif +#endif /* USE_LASERXT */ ret = (kbd->pd & 0x0d) | (hasfpu ? 0x02 : 0x00); } } @@ -1036,7 +1292,7 @@ const device_t keyboard_xt_t1x00_device = { .config = NULL }; -#if defined(DEV_BRANCH) && defined(USE_LASERXT) +#ifdef USE_LASERXT const device_t keyboard_xt_lxt3_device = { .name = "VTech Laser XT3 Keyboard", .internal_name = "keyboard_xt_lxt3", @@ -1050,7 +1306,7 @@ const device_t keyboard_xt_lxt3_device = { .force_redraw = NULL, .config = NULL }; -#endif +#endif /* USE_LASERXT */ const device_t keyboard_xt_olivetti_device = { .name = "Olivetti XT Keyboard", diff --git a/src/device/mouse.c b/src/device/mouse.c index d02144c00b..930c963aba 100644 --- a/src/device/mouse.c +++ b/src/device/mouse.c @@ -99,6 +99,7 @@ static mouse_t mouse_devices[] = { { &mouse_wacom_device }, { &mouse_wacom_artpad_device }, #endif + { &mouse_mtouch_device }, { NULL } // clang-format on }; @@ -482,10 +483,10 @@ mouse_subtract_z(int *delta_z, int min, int max, int invert) int z = atomic_load(&mouse_z); int real_z = invert ? -z : z; - if (mouse_z > max) { + if (real_z > max) { *delta_z = max; real_z -= max; - } else if (mouse_z < min) { + } else if (real_z < min) { *delta_z = min; real_z += ABS(min); } else { diff --git a/src/device/mouse_microtouch_touchscreen.c b/src/device/mouse_microtouch_touchscreen.c new file mode 100644 index 0000000000..ce87a4b687 --- /dev/null +++ b/src/device/mouse_microtouch_touchscreen.c @@ -0,0 +1,497 @@ +/* + * 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. + * + * 3M MicroTouch Serial emulation. + * + * + * + * Authors: Cacodemon345, mourix + * + * Copyright 2024 Cacodemon345 + */ + +/* Reference: https://www.touchwindow.com/mm5/drivers/mtsctlrm.pdf */ + +/* TODO: + - Properly implement GP/SP commands (formats are not documented at all, like anywhere; no dumps yet). + - Add additional SMT2/3 formats as we currently only support Tablet, Hex and Dec. + - Mode Polled. +*/ +#include +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/timer.h> +#include <86box/mouse.h> +#include <86box/serial.h> +#include <86box/plat.h> +#include <86box/fifo8.h> +#include <86box/fifo.h> +#include <86box/video.h> /* Needed to account for overscan. */ + +enum mtouch_formats { + FORMAT_DEC = 1, + FORMAT_HEX = 2, + FORMAT_RAW = 3, + FORMAT_TABLET = 4 +}; + +enum mtouch_modes { + MODE_DOWNUP = 1, + MODE_INACTIVE = 2, + MODE_POINT = 3, + MODE_STREAM = 4, +}; + +const char* mtouch_identity[] = { + "A30100", /* SMT2 Serial / SMT3(R)V */ + "A40100", /* SMT2 PCBus */ + "P50100", /* TouchPen 4(+) */ + "Q10100", /* SMT3(R) Serial */ +}; + +typedef struct mouse_microtouch_t { + double baud_rate, abs_x, abs_x_old, abs_y, abs_y_old; + int but, but_old; + char cmd[256]; + int cmd_pos; + uint8_t format, mode; + bool mode_status; + uint8_t id, cal_cntr, pen_mode; + bool soh; + bool in_reset, reset; + serial_t *serial; + Fifo8 resp; + pc_timer_t host_to_serial_timer; + pc_timer_t reset_timer; +} mouse_microtouch_t; + +static mouse_microtouch_t *mtouch_inst = NULL; + +void +microtouch_reset_complete(void *priv) +{ + mouse_microtouch_t *mtouch = (mouse_microtouch_t *) priv; + + mtouch->reset = true; + mtouch->in_reset = false; + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x30\x0D", 3); /* 0 */ +} + +void +microtouch_calibrate_timer(void *priv) +{ + mouse_microtouch_t *mtouch = (mouse_microtouch_t *) priv; + + if (!fifo8_num_used(&mtouch->resp)) { + mtouch->cal_cntr--; + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x31\x0D", 3); /* 1 */ + } +} + +void +microtouch_process_commands(mouse_microtouch_t *mtouch) +{ + mtouch->cmd[strcspn(mtouch->cmd, "\r")] = '\0'; + pclog("MT Command: %s\n", mtouch->cmd); + + if (mtouch->cmd[0] == 'C' && (mtouch->cmd[1] == 'N' || mtouch->cmd[1] == 'X')) { /* Calibrate New/Extended */ + mtouch->cal_cntr = 2; + } + else if (mtouch->cmd[0] == 'F' && mtouch->cmd[1] == 'D') { /* Format Decimal */ + mtouch->format = FORMAT_DEC; + mtouch->mode_status = false; + } + else if (mtouch->cmd[0] == 'F' && mtouch->cmd[1] == 'O') { /* Finger Only */ + mtouch->pen_mode = 1; + } + else if (mtouch->cmd[0] == 'F' && mtouch->cmd[1] == 'H') { /* Format Hexadecimal */ + mtouch->format = FORMAT_HEX; + mtouch->mode_status = false; + } + else if (mtouch->cmd[0] == 'F' && mtouch->cmd[1] == 'R') { /* Format Raw */ + mtouch->format = FORMAT_RAW; + mtouch->mode = MODE_INACTIVE; + mtouch->cal_cntr = 0; + } + else if (mtouch->cmd[0] == 'F' && mtouch->cmd[1] == 'T') { /* Format Tablet */ + mtouch->format = FORMAT_TABLET; + } + else if (mtouch->cmd[0] == 'G' && mtouch->cmd[1] == 'P' && mtouch->cmd[2] == '1') { /* Get Parameter Block 1 */ + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x41\x0D", 3); /* A */ + fifo8_push_all(&mtouch->resp, (uint8_t *) "0000000000000000000000000\r", 26); + } + else if (mtouch->cmd[0] == 'M' && mtouch->cmd[1] == 'D' && mtouch->cmd[2] == 'U') { /* Mode Down/Up */ + mtouch->mode = MODE_DOWNUP; + } + else if (mtouch->cmd[0] == 'M' && mtouch->cmd[1] == 'I') { /* Mode Inactive */ + mtouch->mode = MODE_INACTIVE; + } + else if (mtouch->cmd[0] == 'M' && mtouch->cmd[1] == 'P') { /* Mode Point */ + mtouch->mode = MODE_POINT; + } + else if (mtouch->cmd[0] == 'M' && mtouch->cmd[1] == 'T') { /* Mode Status */ + mtouch->mode_status = true; + } + else if (mtouch->cmd[0] == 'M' && mtouch->cmd[1] == 'S') { /* Mode Stream */ + mtouch->mode = MODE_STREAM; + } + else if (mtouch->cmd[0] == 'O' && mtouch->cmd[1] == 'I') { /* Output Identity */ + fifo8_push(&mtouch->resp, 0x01); + fifo8_push_all(&mtouch->resp, (uint8_t *) mtouch_identity[mtouch->id], 6); + fifo8_push(&mtouch->resp, 0x0D); + return; + } + else if (mtouch->cmd[0] == 'O' && mtouch->cmd[1] == 'S') { /* Output Status */ + if (mtouch->reset) { + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x40\x60\x0D", 4); + } else { + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x40\x40\x0D", 4); + } + return; + } + else if (mtouch->cmd[0] == 'P') { + if (strlen(mtouch->cmd) == 2) { /* Pen */ + if (mtouch->cmd[1] == 'F') mtouch->pen_mode = 3; /* Pen or Finger */ + else if (mtouch->cmd[1] == 'O') mtouch->pen_mode = 2; /* Pen Only */ + } + else if (strlen(mtouch->cmd) == 5) { /* Serial Options */ + if (mtouch->cmd[4] == 1) mtouch->baud_rate = 19200; + else if (mtouch->cmd[4] == 2) mtouch->baud_rate = 9600; + else if (mtouch->cmd[4] == 3) mtouch->baud_rate = 4600; + else if (mtouch->cmd[4] == 4) mtouch->baud_rate = 2400; + else if (mtouch->cmd[4] == 5) mtouch->baud_rate = 1200; + + timer_stop(&mtouch->host_to_serial_timer); + timer_on_auto(&mtouch->host_to_serial_timer, (1000000. / mtouch->baud_rate) * 10); + } + } + else if (mtouch->cmd[0] == 'R') { /* Reset */ + mtouch->in_reset = true; + mtouch->cal_cntr = 0; + mtouch->pen_mode = 3; + + if (mtouch->cmd[0] == 'D') { /* Restore Defaults */ + mtouch->mode = MODE_STREAM; + mtouch->mode_status = false; + + if (mtouch->id < 2) { + mtouch->format = FORMAT_DEC; + } else { + mtouch->format = FORMAT_TABLET; + } + } + + timer_on_auto(&mtouch->reset_timer, 500. * 1000.); + return; + } + else if (mtouch->cmd[0] == 'S' && mtouch->cmd[1] == 'P' && mtouch->cmd[2] == '1') { /* Set Parameter Block 1 */ + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x41\x0D", 3); /* A */ + return; + } + else if (mtouch->cmd[0] == 'U' && mtouch->cmd[1] == 'T') { /* Unit Type */ + fifo8_push(&mtouch->resp, 0x01); + + if (mtouch->id == 2) { + fifo8_push_all(&mtouch->resp, (uint8_t *) "TP****00", 8); + } else { + fifo8_push_all(&mtouch->resp, (uint8_t *) "QM****00", 8); + } + fifo8_push(&mtouch->resp, 0x0D); + return; + } + + fifo8_push_all(&mtouch->resp, (uint8_t *) "\x01\x30\x0D", 3); /* 0 */ +} + +void +mtouch_write(serial_t *serial, void *priv, uint8_t data) +{ + mouse_microtouch_t *dev = (mouse_microtouch_t *) priv; + if (data == '\x1') { + dev->soh = 1; + } + else if (dev->soh) { + if (data != '\r') { + dev->cmd[dev->cmd_pos++] = data; + } else { + dev->soh = 0; + + if (!dev->cmd_pos) { + return; + } + + dev->cmd[dev->cmd_pos++] = data; + dev->cmd_pos = 0; + microtouch_process_commands(dev); + } + } +} + +static int +mtouch_prepare_transmit(void *priv) +{ + char buffer[16]; + mouse_microtouch_t *dev = (mouse_microtouch_t *) priv; + + double abs_x = dev->abs_x; + double abs_y = dev->abs_y; + int but = dev->but; + + if (dev->mode == MODE_INACTIVE) { + return 0; + } + + if (dev->cal_cntr || (!dev->but && !dev->but_old)) { /* Calibration or no buttonpress */ + if (!dev->but && dev->but_old) { + microtouch_calibrate_timer(dev); + } + dev->but_old = but; /* Save buttonpress */ + return 0; + } + + if (dev->format == FORMAT_TABLET) { + if (but) { /* Touchdown/Continuation */ + fifo8_push(&dev->resp, 0b11000000 | ((dev->pen_mode == 2) ? ((1 << 5) | ((but & 3))) : 0)); + fifo8_push(&dev->resp, (uint16_t)(16383 * abs_x) & 0b1111111); + fifo8_push(&dev->resp, ((uint16_t)(16383 * abs_x) >> 7) & 0b1111111); + fifo8_push(&dev->resp, (uint16_t)(16383 * (1 - abs_y)) & 0b1111111); + fifo8_push(&dev->resp, ((uint16_t)(16383 * (1 - abs_y)) >> 7) & 0b1111111); + } + else if (dev->but_old) { /* Liftoff */ + fifo8_push(&dev->resp, 0b10000000 | ((dev->pen_mode == 2) ? ((1 << 5)) : 0)); + fifo8_push(&dev->resp, (uint16_t)(16383 * dev->abs_x_old) & 0b1111111); + fifo8_push(&dev->resp, ((uint16_t)(16383 * dev->abs_x_old) >> 7) & 0b1111111); + fifo8_push(&dev->resp, (uint16_t)(16383 * (1 - dev->abs_y_old))& 0b1111111); + fifo8_push(&dev->resp, ((uint16_t)(16383 * (1 - dev->abs_y_old)) >> 7) & 0b1111111); + } + } + + else if (dev->format == FORMAT_DEC || dev->format == FORMAT_HEX) { + if (but) { + if (!dev->but_old) { /* Touchdown (MS, MP, MDU) */ + fifo8_push(&dev->resp, (dev->mode_status) ? 0x19 : 0x01); + if (dev->format == FORMAT_DEC){ + snprintf(buffer, sizeof(buffer), "%03d,%03d\r", (uint16_t)(999 * abs_x), (uint16_t)(999 * (1 - abs_y))); + } + else if (dev->format == FORMAT_HEX) { + snprintf(buffer, sizeof(buffer), "%03X,%03X\r", (uint16_t)(1023 * abs_x), (uint16_t)(1023 * (1 - abs_y))); + } + fifo8_push_all(&dev->resp, (uint8_t *)buffer, strlen(buffer)); + } + else if (dev->mode == MODE_STREAM){ /* Touch Continuation (MS) */ + fifo8_push(&dev->resp, (dev->mode_status) ? 0x1c : 0x01); + if (dev->format == FORMAT_DEC){ + snprintf(buffer, sizeof(buffer), "%03d,%03d\r", (uint16_t)(999 * abs_x), (uint16_t)(999 * (1 - abs_y))); + } + else if (dev->format == FORMAT_HEX) { + snprintf(buffer, sizeof(buffer), "%03X,%03X\r", (uint16_t)(1023 * abs_x), (uint16_t)(1023 * (1 - abs_y))); + } + fifo8_push_all(&dev->resp, (uint8_t *)buffer, strlen(buffer)); + } + } + else if (dev->but_old && dev->mode != MODE_POINT) { /* Touch Liftoff (MS, MDU) */ + fifo8_push(&dev->resp, (dev->mode_status) ? 0x18 : 0x01); + if (dev->format == FORMAT_DEC) { + snprintf(buffer, sizeof(buffer), "%03d,%03d\r", (uint16_t)(999 * dev->abs_x_old), (uint16_t)(999 * (1 - dev->abs_y_old))); + } + else if (dev->format == FORMAT_HEX) { + snprintf(buffer, sizeof(buffer), "%03X,%03X\r", (uint16_t)(1023 * dev->abs_x_old), (uint16_t)(1023 * (1 - dev->abs_y_old))); + } + fifo8_push_all(&dev->resp, (uint8_t *)buffer, strlen(buffer)); + } + } + + /* Save old states*/ + dev->abs_x_old = abs_x; + dev->abs_y_old = abs_y; + dev->but_old = but; + return 0; +} + +void +mtouch_write_to_host(void *priv) +{ + mouse_microtouch_t *dev = (mouse_microtouch_t *) priv; + if (dev->serial == NULL) + goto no_write_to_machine; + if ((dev->serial->type >= SERIAL_16550) && dev->serial->fifo_enabled) { + if (fifo_get_full(dev->serial->rcvr_fifo)) { + goto no_write_to_machine; + } + } else { + if (dev->serial->lsr & 1) { + goto no_write_to_machine; + } + } + if (dev->in_reset) { + goto no_write_to_machine; + } + if (fifo8_num_used(&dev->resp)) { + serial_write_fifo(dev->serial, fifo8_pop(&dev->resp)); + } + else { + mtouch_prepare_transmit(dev); + } + +no_write_to_machine: + timer_on_auto(&dev->host_to_serial_timer, (1000000.0 / (double) dev->baud_rate) * (double) (1 + 8 + 1)); +} + +static int +mtouch_poll(void *priv) +{ + mouse_microtouch_t *dev = (mouse_microtouch_t *) priv; + + dev->but = mouse_get_buttons_ex(); + mouse_get_abs_coords(&dev->abs_x, &dev->abs_y); + + if (enable_overscan) { + int index = mouse_tablet_in_proximity - 1; + if (mouse_tablet_in_proximity == -1) { + mouse_tablet_in_proximity = 0; + } + + dev->abs_x *= monitors[index].mon_unscaled_size_x - 1; + dev->abs_y *= monitors[index].mon_efscrnsz_y - 1; + + if (dev->abs_x <= (monitors[index].mon_overscan_x / 2.)) { + dev->abs_x = (monitors[index].mon_overscan_x / 2.); + } + if (dev->abs_y <= (monitors[index].mon_overscan_y / 2.)) { + dev->abs_y = (monitors[index].mon_overscan_y / 2.); + } + dev->abs_x -= (monitors[index].mon_overscan_x / 2.); + dev->abs_y -= (monitors[index].mon_overscan_y / 2.); + dev->abs_x = dev->abs_x / (double) monitors[index].mon_xsize; + dev->abs_y = dev->abs_y / (double) monitors[index].mon_ysize; + } + + if (dev->abs_x >= 1.0) dev->abs_x = 1.0; + if (dev->abs_y >= 1.0) dev->abs_y = 1.0; + if (dev->abs_x <= 0.0) dev->abs_x = 0.0; + if (dev->abs_y <= 0.0) dev->abs_y = 0.0; + + return 0; +} + +static void +mtouch_poll_global(void) +{ + mtouch_poll(mtouch_inst); +} + +void * +mtouch_init(const device_t *info) +{ + mouse_microtouch_t *dev = calloc(1, sizeof(mouse_microtouch_t)); + + dev->serial = serial_attach(device_get_config_int("port"), NULL, mtouch_write, dev); + dev->baud_rate = 9600; + serial_set_cts(dev->serial, 1); + serial_set_dsr(dev->serial, 1); + serial_set_dcd(dev->serial, 1); + + fifo8_create(&dev->resp, 256); + timer_add(&dev->host_to_serial_timer, mtouch_write_to_host, dev, 0); + timer_add(&dev->reset_timer, microtouch_reset_complete, dev, 0); + timer_on_auto(&dev->host_to_serial_timer, (1000000. / dev->baud_rate) * 10); + dev->id = device_get_config_int("identity"); + dev->pen_mode = 3; + dev->mode = MODE_STREAM; + + if (dev->id < 2) { /* legacy controllers */ + dev->format = FORMAT_DEC; + } else { + dev->format = FORMAT_TABLET; + } + + mouse_input_mode = device_get_config_int("crosshair") + 1; + mouse_set_buttons(2); + mouse_set_poll_ex(mtouch_poll_global); + mtouch_inst = dev; + + return dev; +} + +void +mtouch_close(void *priv) +{ + mouse_microtouch_t *dev = (mouse_microtouch_t *) priv; + + fifo8_destroy(&dev->resp); + /* Detach serial port from the mouse. */ + if (dev && dev->serial && dev->serial->sd) { + memset(dev->serial->sd, 0, sizeof(serial_device_t)); + } + + free(dev); + mtouch_inst = NULL; +} + +static const device_config_t mtouch_config[] = { + // clang-format off + { + .name = "port", + .description = "Serial Port", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "COM1", .value = 0 }, + { .description = "COM2", .value = 1 }, + { .description = "COM3", .value = 2 }, + { .description = "COM4", .value = 3 }, + { .description = "" } + } + }, + { + .name = "identity", + .description = "Controller", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = NULL, + .spinner = { 0 }, + .selection = { + { .description = "A3 - SMT2 Serial / SMT3(R)V", .value = 0 }, + { .description = "A4 - SMT2 PCBus", .value = 1 }, + { .description = "P5 - TouchPen 4(+)", .value = 2 }, + { .description = "Q1 - SMT3(R) Serial", .value = 3 } + } + }, + { + .name = "crosshair", + .description = "Show Crosshair", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +const device_t mouse_mtouch_device = { + .name = "3M MicroTouch (Serial)", + .internal_name = "microtouch_touchpen", + .flags = DEVICE_COM, + .local = 0, + .init = mtouch_init, + .close = mtouch_close, + .reset = NULL, + { .poll = mtouch_poll }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = mtouch_config +}; \ No newline at end of file diff --git a/src/device/mouse_serial.c b/src/device/mouse_serial.c index 08aee09d86..afc662a198 100644 --- a/src/device/mouse_serial.c +++ b/src/device/mouse_serial.c @@ -142,7 +142,8 @@ sermouse_transmit_byte(mouse_t *dev, int do_next) if (dev->buf_pos == 0) dev->acc_time = 0.0; - serial_write_fifo(dev->serial, dev->buf[dev->buf_pos]); + if (dev->serial) + serial_write_fifo(dev->serial, dev->buf[dev->buf_pos]); if (do_next) { dev->buf_pos = (dev->buf_pos + 1) % dev->buf_len; diff --git a/src/device/serial.c b/src/device/serial.c index ab26fc6227..2b832f7506 100644 --- a/src/device/serial.c +++ b/src/device/serial.c @@ -223,7 +223,7 @@ serial_write_fifo(serial_t *dev, uint8_t dat) ((dev->type >= SERIAL_16550) && dev->fifo_enabled) ? fifo_get_count(dev->rcvr_fifo) : 0); - if (!(dev->mctrl & 0x10)) + if ((dev != NULL) && !(dev->mctrl & 0x10)) write_fifo(dev, dat); } @@ -597,7 +597,7 @@ serial_write(uint16_t addr, uint8_t val, void *priv) serial_reset_fifo(dev); if (dev->sd && dev->sd->dtr_callback && (val ^ dev->mctrl) & 1) dev->sd->dtr_callback(dev, val & 1, dev->sd->priv); - dev->mctrl = val; + dev->mctrl = val & 0x1f; if (val & 0x10) { new_msr = (val & 0x0c) << 4; new_msr |= (val & 0x02) ? 0x10 : 0; @@ -912,7 +912,13 @@ serial_init(const device_t *info) memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t)); dev->sd = &(serial_devices[next_inst]); dev->sd->serial = dev; - if (next_inst == 3) + if (next_inst == 6) + serial_setup(dev, COM7_ADDR, COM7_IRQ); + else if (next_inst == 5) + serial_setup(dev, COM6_ADDR, COM6_IRQ); + else if (next_inst == 4) + serial_setup(dev, COM5_ADDR, COM5_IRQ); + else if (next_inst == 3) serial_setup(dev, COM4_ADDR, COM4_IRQ); else if (next_inst == 2) serial_setup(dev, COM3_ADDR, COM3_IRQ); diff --git a/src/device/smbus_sis5595.c b/src/device/smbus_sis5595.c index b76b38e170..191e7a6a52 100644 --- a/src/device/smbus_sis5595.c +++ b/src/device/smbus_sis5595.c @@ -148,7 +148,7 @@ smbus_sis5595_read_data(void *priv) break; } - smbus_sis5595_log("SMBus SIS5595: read(%02X) = %02x\n", addr, ret); + smbus_sis5595_log("SMBus SIS5595: read(%02X) = %02x\n", dev->addr, ret); return ret; } @@ -171,7 +171,7 @@ smbus_sis5595_write_data(void *priv, uint8_t val) uint16_t prev_stat; uint16_t timer_bytes = 0; - smbus_sis5595_log("SMBus SIS5595: write(%02X, %02X)\n", addr, val); + smbus_sis5595_log("SMBus SIS5595: write(%02X, %02X)\n", dev->addr, val); prev_stat = dev->next_stat; dev->next_stat = 0x0000; diff --git a/src/disk/CMakeLists.txt b/src/disk/CMakeLists.txt index 87b9593fae..3f6a4d018f 100644 --- a/src/disk/CMakeLists.txt +++ b/src/disk/CMakeLists.txt @@ -9,14 +9,33 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(hdd OBJECT hdd.c hdd_image.c hdd_table.c hdc.c hdc_st506_xt.c - hdc_st506_at.c hdc_xta.c hdc_esdi_at.c hdc_esdi_mca.c hdc_xtide.c - hdc_ide.c hdc_ide_ali5213.c hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c - hdc_ide_sff8038i.c hdc_ide_um8673f.c hdc_ide_w83769f.c lba_enhancer.c) +add_library(hdd OBJECT + hdd.c + hdd_image.c + hdd_table.c + hdc.c + hdc_st506_xt.c + hdc_st506_at.c + hdc_xta.c + hdc_esdi_at.c + hdc_esdi_mca.c + hdc_xtide.c + hdc_ide.c + hdc_ide_ali5213.c + hdc_ide_opti611.c + hdc_ide_cmd640.c + hdc_ide_cmd646.c + hdc_ide_sff8038i.c + hdc_ide_um8673f.c + hdc_ide_w83769f.c + lba_enhancer.c +) add_library(zip OBJECT zip.c) diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 034b8890e3..908cbce072 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -30,7 +30,7 @@ #include <86box/hdc_ide.h> #include <86box/hdd.h> -int hdc_current; +int hdc_current[HDC_MAX] = { 0, 0 }; #ifdef ENABLE_HDC_LOG int hdc_do_log = ENABLE_HDC_LOG; @@ -50,40 +50,12 @@ hdc_log(const char *fmt, ...) # define hdc_log(fmt, ...) #endif -static const device_t hdc_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -static const device_t hdc_internal_device = { - .name = "Internal", - .internal_name = "internal", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const struct { const device_t *device; } controllers[] = { // clang-format off - { &hdc_none_device }, - { &hdc_internal_device }, + { &device_none }, + { &device_internal }, { &st506_xt_xebec_device }, { &st506_xt_wdxt_gen_device }, { &st506_xt_dtc5150x_device }, @@ -129,11 +101,11 @@ void hdc_reset(void) { hdc_log("HDC: reset(current=%d, internal=%d)\n", - hdc_current, (machines[machine].flags & MACHINE_HDC) ? 1 : 0); + hdc_current[0], (machines[machine].flags & MACHINE_HDC) ? 1 : 0); /* If we have a valid controller, add its device. */ - if (hdc_current > 1) - device_add(controllers[hdc_current].device); + if (hdc_current[0] > HDC_INTERNAL) + device_add(controllers[hdc_current[0]].device); /* Now, add the tertiary and/or quaternary IDE controllers. */ if (ide_ter_enabled) diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index c906c7ca1f..1061cbc78e 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -188,6 +188,7 @@ typedef struct esdi_t { #define CMD_READ_VERIFY 0x03 #define CMD_WRITE_VERIFY 0x04 #define CMD_SEEK 0x05 +#define CMD_PARK_HEADS 0x06 #define CMD_GET_DEV_STATUS 0x08 #define CMD_GET_DEV_CONFIG 0x09 #define CMD_GET_POS_INFO 0x0a @@ -371,7 +372,9 @@ esdi_callback(void *priv) if (dev->in_reset) { esdi_mca_log("ESDI reset.\n"); dev->in_reset = 0; - dev->status = STATUS_IRQ; + dev->status = STATUS_IRQ | STATUS_TRANSFER_REQ | STATUS_STATUS_OUT_FULL; + dev->status_len = 1; /*ToDo: better implementation for Xenix?*/ + dev->status_data[0] = STATUS_LEN(1) | ATTN_HOST_ADAPTER; dev->irq_status = IRQ_HOST_ADAPTER | IRQ_RESET_COMPLETE; return; } @@ -605,6 +608,35 @@ esdi_callback(void *priv) } break; + case CMD_PARK_HEADS: + ESDI_DRIVE_ONLY(); + + if (!drive->present) { + device_not_present(dev); + return; + } + + switch (dev->cmd_state) { + case 0: + dev->rba = 0x00000000; + cmd_time = hdd_seek_get_time(&hdd[drive->hdd_num], dev->rba, HDD_OP_SEEK, 0, 0.0); + esdi_mca_set_callback(dev, ESDI_TIME + cmd_time); + dev->cmd_state = 1; + break; + + case 1: + complete_command_status(dev); + dev->status = STATUS_IRQ | STATUS_STATUS_OUT_FULL; + dev->irq_status = dev->cmd_dev | IRQ_CMD_COMPLETE_SUCCESS; + dev->irq_in_progress = 1; + set_irq(dev); + break; + + default: + break; + } + break; + case CMD_GET_DEV_STATUS: ESDI_DRIVE_ONLY(); @@ -1025,8 +1057,10 @@ esdi_readw(uint16_t port, void *priv) switch (port & 7) { case 0: /*Status Interface Register*/ - if (dev->status_pos >= dev->status_len) + if (dev->status_pos >= dev->status_len) { + esdi_mca_log("esdi_readw port=%04x, ret=0000 (pos=%d, len=%d).\n", port, dev->status_pos, dev->status_len); return 0; + } ret = dev->status_data[dev->status_pos++]; if (dev->status_pos >= dev->status_len) { dev->status &= ~STATUS_STATUS_OUT_FULL; @@ -1038,6 +1072,7 @@ esdi_readw(uint16_t port, void *priv) fatal("esdi_readw port=%04x\n", port); } + esdi_mca_log("esdi_readw port=%04x, ret=%04x.\n", port, ret); return ret; } @@ -1220,7 +1255,7 @@ esdi_init(UNUSED(const device_t *info)) drive->spt = hdd[i].spt; drive->hpc = hdd[i].hpc; drive->tracks = hdd[i].tracks; - drive->sectors = hdd_image_get_last_sector(i) + 1; + drive->sectors = hdd_image_get_last_sector(i); drive->hdd_num = i; /* Mark drive as present. */ diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 3793f778be..1ec054de91 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -1252,7 +1252,10 @@ ide_write_data(ide_t *ide, const uint16_t val) const double xfer_time = ide_get_xfer_time(ide, 512); const double wait_time = seek_time + xfer_time; if (ide->command == WIN_WRITE_MULTIPLE) { - if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) { + if (hdd[ide->hdd_num].speed_preset == 0) { + ide->pending_delay = 0; + ide_callback(ide); + } else if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) { ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay); ide->pending_delay = 0; } else { @@ -1607,9 +1610,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide->sc->callback = 100.0 * IDE_TIME; ide_set_callback(ide, 100.0 * IDE_TIME); } else { - double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], (val & 0x60) ? - ide_get_sector(ide) : 0, HDD_OP_SEEK, 0, 0.0); - ide_set_callback(ide, seek_time); + if (hdd[ide->hdd_num].speed_preset == 0) + ide_set_callback(ide, 100.0 * IDE_TIME); + else { + double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], (val & 0x60) ? + ide_get_sector(ide) : 0, HDD_OP_SEEK, 0, 0.0); + ide_set_callback(ide, seek_time); + } } break; @@ -1652,6 +1659,10 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide_get_sector(ide), sec_count); double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); wait_time = seek_time > xfer_time ? seek_time : xfer_time; + } else if ((val == WIN_READ_MULTIPLE) && (hdd[ide->hdd_num].speed_preset == 0)) { + ide_set_callback(ide, 200.0 * IDE_TIME); + ide->do_initial_read = 1; + break; } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize > 0)) { sec_count = ide->tf->secount ? ide->tf->secount : 256; if (sec_count > ide->blocksize) @@ -1848,7 +1859,9 @@ ide_read_data(ide_t *ide) ide_next_sector(ide); ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT; if (ide->command == WIN_READ_MULTIPLE) { - if (!ide->blockcount) { + if (hdd[ide->hdd_num].speed_preset == 0) + ide_callback(ide); + else if (!ide->blockcount) { uint32_t cnt = ide->tf->secount ? ide->tf->secount : 256; if (cnt > ide->blocksize) @@ -1888,8 +1901,7 @@ ide_status(ide_t *ide, ide_t *ide_other, int ch) /* On real hardware, a slave with a present master always returns a status of 0x00. Confirmed by the ATA-3 and ATA-4 specifications. */ - // ret = 0x00; - ret = 0x01; + ret = 0x00; } else { ret = ide->tf->atastat; if (ide->type == IDE_ATAPI) diff --git a/src/disk/hdc_ide_ali5213.c b/src/disk/hdc_ide_ali5213.c index eee3844c4c..8ff3d392cf 100644 --- a/src/disk/hdc_ide_ali5213.c +++ b/src/disk/hdc_ide_ali5213.c @@ -83,7 +83,7 @@ ali5213_write(uint16_t addr, uint8_t val, void *priv) { ali5213_t *dev = (ali5213_t *) priv; - ali5213_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries); + ali5213_log("[%04X:%08X] [W] %02X = %02X\n", CS, cpu_state.pc, addr, val); switch (addr) { case 0xf4: /* Usually it writes 30h here */ @@ -179,7 +179,7 @@ ali5213_read(uint16_t addr, void *priv) break; } - ali5213_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret); + ali5213_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, addr, ret); return ret; } diff --git a/src/disk/hdc_ide_um8673f.c b/src/disk/hdc_ide_um8673f.c index 9ee149c7f3..bc046dd267 100644 --- a/src/disk/hdc_ide_um8673f.c +++ b/src/disk/hdc_ide_um8673f.c @@ -79,7 +79,7 @@ um8673f_write(uint16_t addr, uint8_t val, void *priv) { um8673f_t *dev = (um8673f_t *) priv; - um8673f_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries); + um8673f_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, addr, val, dev->tries); switch (addr) { case 0x108: @@ -140,7 +140,7 @@ um8673f_read(uint16_t addr, void *priv) break; } - um8673f_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret); + um8673f_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, addr, ret); return ret; } diff --git a/src/disk/hdc_ide_w83769f.c b/src/disk/hdc_ide_w83769f.c index ed34bc9fc2..c2b0538145 100644 --- a/src/disk/hdc_ide_w83769f.c +++ b/src/disk/hdc_ide_w83769f.c @@ -59,7 +59,7 @@ w83769f_log(const char *fmt, ...) { va_list ap; - if (cmd640_do_log) { + if (w83769f_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index f3ac48a36a..47e6f045ab 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -1683,7 +1683,7 @@ st506_init(const device_t *info) dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) - dev->switches |= 0x40; + dev->switches |= 0x80; dev->bios_addr = device_get_config_hex20("bios_addr"); break; @@ -1702,7 +1702,7 @@ st506_init(const device_t *info) dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) - dev->switches |= 0x40; + dev->switches |= 0x80; dev->bios_addr = device_get_config_hex20("bios_addr"); break; @@ -1717,7 +1717,7 @@ st506_init(const device_t *info) dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) - dev->switches |= 0x40; + dev->switches |= 0x80; dev->bios_addr = device_get_config_hex20("bios_addr"); break; @@ -1732,7 +1732,7 @@ st506_init(const device_t *info) dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) - dev->switches |= 0x40; + dev->switches |= 0x80; dev->bios_addr = device_get_config_hex20("bios_addr"); break; @@ -1747,7 +1747,7 @@ st506_init(const device_t *info) dev->base = device_get_config_hex16("base"); dev->irq = device_get_config_int("irq"); if (dev->irq == 2) - dev->switches |= 0x40; + dev->switches |= 0x80; dev->bios_addr = device_get_config_hex20("bios_addr"); break; diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index db56d5b786..7c26189694 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -26,6 +26,9 @@ #include #include #include +#ifdef __unix__ +#include +#endif #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/path.h> @@ -183,6 +186,7 @@ prepare_new_hard_disk(uint8_t id, uint64_t full_size) { uint64_t target_size = (full_size + hdd_images[id].base) - ftello64(hdd_images[id].file); +#ifndef __unix__ uint32_t size; uint32_t t; @@ -217,7 +221,16 @@ prepare_new_hard_disk(uint8_t id, uint64_t full_size) pclog_toggle_suppr(); free(empty_sector_1mb); +#else + pclog("Creating hard disk image: "); + int ret = ftruncate(fileno(hdd_images[id].file), (size_t) target_size); + if (ret) { + pclog("failed\n"); + fatal("Could not create hard disk image\n"); + } + pclog("OK!\n"); +#endif hdd_images[id].last_sector = (uint32_t) (full_size >> 9) - 1; hdd_images[id].loaded = 1; @@ -564,6 +577,7 @@ hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) } num_write = fwrite(buffer, 512, count, hdd_images[id].file); + fflush(hdd_images[id].file); hdd_images[id].pos = sector + num_write; } } @@ -605,6 +619,8 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) hdd_images[id].pos = sector + i; fwrite(empty_sector, 512, 1, hdd_images[id].file); } + + fflush(hdd_images[id].file); } } diff --git a/src/disk/minivhd/minivhd_io.c b/src/disk/minivhd/minivhd_io.c index 2912cf5b2e..1a349dbc48 100644 --- a/src/disk/minivhd/minivhd_io.c +++ b/src/disk/minivhd/minivhd_io.c @@ -37,6 +37,7 @@ #ifndef _FILE_OFFSET_BITS # define _FILE_OFFSET_BITS 64 #endif +#include #include #include #include @@ -45,6 +46,10 @@ #include #include "minivhd.h" #include "internal.h" +#define HAVE_STDARG_H + +#include "cpu.h" +#include <86box/86box.h> /* * The following bit array macros adapted from: @@ -84,6 +89,8 @@ mvhd_write_empty_sectors(FILE *f, int sector_count) for (int i = 0; i < sector_count; i++) fwrite(zero_bytes, sizeof zero_bytes, 1, f); + + fflush(f); } /** @@ -136,6 +143,7 @@ write_bat_entry(MVHDMeta *vhdm, int blk) mvhd_fseeko64(vhdm->f, table_offset, SEEK_SET); fwrite(&offset, sizeof offset, 1, vhdm->f); + fflush(vhdm->f); } /** @@ -192,6 +200,8 @@ create_block(MVHDMeta *vhdm, int blk) /* We no longer have a sparse block. Update that BAT! */ vhdm->block_offset[blk] = sect_offset; write_bat_entry(vhdm, blk); + + fflush(vhdm->f); } int @@ -312,6 +322,7 @@ mvhd_fixed_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *in_buff addr = (int64_t)offset * MVHD_SECTOR_SIZE; mvhd_fseeko64(vhdm->f, addr, SEEK_SET); fwrite(in_buff, transfer_sectors * MVHD_SECTOR_SIZE, 1, vhdm->f); + fflush(vhdm->f); return truncated_sectors; } @@ -334,41 +345,45 @@ mvhd_sparse_diff_write(MVHDMeta *vhdm, uint32_t offset, int num_sectors, void *i int sib = 0; ls = offset + transfer_sectors; - for (s = offset; s < ls; s++) { - blk = s / vhdm->sect_per_block; - sib = s % vhdm->sect_per_block; - if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) { - /* Write the sector bitmap for the previous block, before we replace it. */ - write_curr_sect_bitmap(vhdm); - } - - if (vhdm->block_offset[blk] == MVHD_SPARSE_BLK) { - /* "read" the sector bitmap first, before creating a new block, as the bitmap will be - zero either way */ - read_sect_bitmap(vhdm, blk); - create_block(vhdm, blk); - } + if (offset < total_sectors) { + for (s = offset; s < ls; s++) { + blk = s / vhdm->sect_per_block; + sib = s % vhdm->sect_per_block; + if (vhdm->bitmap.curr_block != blk && prev_blk >= 0) { + /* Write the sector bitmap for the previous block, before we replace it. */ + write_curr_sect_bitmap(vhdm); + } - if (blk != prev_blk) { - if (vhdm->bitmap.curr_block != blk) { + if (vhdm->block_offset[blk] == MVHD_SPARSE_BLK) { + /* "read" the sector bitmap first, before creating a new block, as the bitmap will be + zero either way */ read_sect_bitmap(vhdm, blk); - mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR); - } else { - addr = (((int64_t) vhdm->block_offset[blk]) + vhdm->bitmap.sector_count + sib) * - MVHD_SECTOR_SIZE; - mvhd_fseeko64(vhdm->f, addr, SEEK_SET); + create_block(vhdm, blk); } - prev_blk = blk; - } - fwrite(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); - VHD_SETBIT(vhdm->bitmap.curr_bitmap, sib); - buff += MVHD_SECTOR_SIZE; + if (blk != prev_blk) { + if (vhdm->bitmap.curr_block != blk) { + read_sect_bitmap(vhdm, blk); + mvhd_fseeko64(vhdm->f, (uint64_t)sib * MVHD_SECTOR_SIZE, SEEK_CUR); + } else { + addr = (((int64_t) vhdm->block_offset[blk]) + vhdm->bitmap.sector_count + sib) * + MVHD_SECTOR_SIZE; + mvhd_fseeko64(vhdm->f, addr, SEEK_SET); + } + prev_blk = blk; + } + + fwrite(buff, MVHD_SECTOR_SIZE, 1, vhdm->f); + VHD_SETBIT(vhdm->bitmap.curr_bitmap, sib); + buff += MVHD_SECTOR_SIZE; + } } /* And write the sector bitmap for the last block we visited to disk */ write_curr_sect_bitmap(vhdm); + fflush(vhdm->f); + return truncated_sectors; } diff --git a/src/disk/mo.c b/src/disk/mo.c index e90267b95b..ed1ab24727 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -701,7 +701,6 @@ mo_command_common(mo_t *dev) static void mo_command_complete(mo_t *dev) { - ui_sb_update_icon(SB_MO | dev->id, 0); dev->packet_status = PHASE_COMPLETE; mo_command_common(dev); } @@ -952,6 +951,8 @@ mo_blocks(mo_t *dev, int32_t *len, UNUSED(int first_batch), int out) if (out) { if (fwrite(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) fatal("mo_blocks(): Error writing data\n"); + + fflush(dev->drv->fp); } else { if (fread(dev->buffer + (i * dev->drv->sector_size), 1, dev->drv->sector_size, dev->drv->fp) != dev->drv->sector_size) fatal("mo_blocks(): Error reading data\n"); @@ -1070,6 +1071,8 @@ mo_erase(mo_t *dev) fwrite(dev->buffer, 1, dev->drv->sector_size, dev->drv->fp); } + fflush(dev->drv->fp); + mo_log("MO %i: Erased %i bytes of blocks...\n", dev->id, i * dev->drv->sector_size); dev->sector_pos += i; diff --git a/src/disk/zip.c b/src/disk/zip.c index d4cbd0b416..a948cab2f5 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -875,7 +875,6 @@ zip_command_common(zip_t *dev) static void zip_command_complete(zip_t *dev) { - ui_sb_update_icon(SB_ZIP | dev->id, 0); dev->packet_status = PHASE_COMPLETE; zip_command_common(dev); } @@ -1135,6 +1134,8 @@ zip_blocks(zip_t *dev, int32_t *len, UNUSED(int first_batch), int out) if (out) { if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) fatal("zip_blocks(): Error writing data\n"); + + fflush(dev->drv->fp); } else { if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->fp) != 512) fatal("zip_blocks(): Error reading data\n"); @@ -2126,6 +2127,8 @@ zip_phase_data_out(scsi_common_t *sc) if (fwrite(dev->buffer, 1, 512, dev->drv->fp) != 512) fatal("zip_phase_data_out(): Error writing data\n"); } + + fflush(dev->drv->fp); break; case GPCMD_MODE_SELECT_6: case GPCMD_MODE_SELECT_10: diff --git a/src/dma.c b/src/dma.c index 0593d03957..86c29fe262 100644 --- a/src/dma.c +++ b/src/dma.c @@ -18,6 +18,7 @@ * Copyright 2016-2020 Miran Grca. * Copyright 2017-2020 Fred N. van Kempen. */ +#include #include #include #include @@ -813,8 +814,6 @@ dma16_read(uint16_t addr, UNUSED(void *priv)) case 7: /*Count registers*/ dma_wp[1] ^= 1; count = dma[channel].cc/* + 1*/; - // if (count > dma[channel].cb) - // count = 0x0000; if (dma_wp[1]) ret = count & 0xff; else @@ -1411,7 +1410,7 @@ dma_retreat(dma_t *dma_c) dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff; dma_c->page_h = (dma_c->ac >> 24) & 0xff; } else if (as == 2) - dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac - as) & 0xffff); + dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac - as) & 0x1ffff); else dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac - as) & 0xffff); } @@ -1427,7 +1426,7 @@ dma_advance(dma_t *dma_c) dma_c->page = dma_c->page_l = (dma_c->ac >> 16) & 0xff; dma_c->page_h = (dma_c->ac >> 24) & 0xff; } else if (as == 2) - dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); + dma_c->ac = ((dma_c->ac & 0xfffe0000) & dma_mask) | ((dma_c->ac + as) & 0x1ffff); else dma_c->ac = ((dma_c->ac & 0xffff0000) & dma_mask) | ((dma_c->ac + as) & 0xffff); } diff --git a/src/fifo8.c b/src/fifo8.c index feef0deb2c..9c73b4e824 100644 --- a/src/fifo8.c +++ b/src/fifo8.c @@ -21,14 +21,19 @@ #include <86box/86box.h> #include <86box/fifo8.h> +void +fifo8_reset(Fifo8 *fifo) +{ + fifo->num = 0; + fifo->head = 0; +} + void fifo8_create(Fifo8 *fifo, uint32_t capacity) { - fifo->data = (uint8_t *) malloc(capacity); - memset(fifo->data, 0, capacity); + fifo->data = (uint8_t *) calloc(1, capacity); fifo->capacity = capacity; - fifo->head = 0; - fifo->num = 0; + fifo8_reset(fifo); } void @@ -54,7 +59,7 @@ fifo8_push_all(Fifo8 *fifo, const uint8_t *data, uint32_t num) uint32_t start; uint32_t avail; - assert(fifo->num + num <= fifo->capacity); + assert((fifo->num + num) <= fifo->capacity); start = (fifo->head + fifo->num) % fifo->capacity; @@ -81,25 +86,72 @@ fifo8_pop(Fifo8 *fifo) return ret; } -const uint8_t * -fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num) +static const uint8_t +*fifo8_peekpop_buf(Fifo8 *fifo, uint32_t max, uint32_t *numptr, int do_pop) { - const uint8_t *ret; + uint8_t *ret; + uint32_t num; + + assert((max > 0) && (max <= fifo->num)); + num = MIN(fifo->capacity - fifo->head, max); + ret = &fifo->data[fifo->head]; + + if (do_pop) { + fifo->head += num; + fifo->head %= fifo->capacity; + fifo->num -= num; + } + if (numptr) + *numptr = num; - assert(max > 0 && max <= fifo->num); - *num = MIN(fifo->capacity - fifo->head, max); - ret = &fifo->data[fifo->head]; - fifo->head += *num; - fifo->head %= fifo->capacity; - fifo->num -= *num; return ret; } +const uint8_t +*fifo8_peek_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr) +{ + return fifo8_peekpop_buf(fifo, max, numptr, 0); +} + +const uint8_t +*fifo8_pop_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr) +{ + return fifo8_peekpop_buf(fifo, max, numptr, 1); +} + +uint32_t +fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen) +{ + const uint8_t *buf; + uint32_t n1, n2 = 0; + uint32_t len; + + if (destlen == 0) + return 0; + + len = destlen; + buf = fifo8_pop_bufptr(fifo, len, &n1); + if (dest) + memcpy(dest, buf, n1); + + /* Add FIFO wraparound if needed */ + len -= n1; + len = MIN(len, fifo8_num_used(fifo)); + if (len) { + buf = fifo8_pop_bufptr(fifo, len, &n2); + if (dest) { + memcpy(&dest[n1], buf, n2); + } + } + + return n1 + n2; +} + void -fifo8_reset(Fifo8 *fifo) +fifo8_drop(Fifo8 *fifo, uint32_t len) { - fifo->num = 0; - fifo->head = 0; + len -= fifo8_pop_buf(fifo, NULL, len); + assert(len == 0); } int diff --git a/src/floppy/CMakeLists.txt b/src/floppy/CMakeLists.txt index 6d69d2d590..d86ff4bc23 100644 --- a/src/floppy/CMakeLists.txt +++ b/src/floppy/CMakeLists.txt @@ -9,10 +9,28 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(fdd OBJECT fdd.c fdc.c fdc_magitronic.c fdc_monster.c fdc_pii15xb.c - fdi2raw.c fdd_common.c fdd_86f.c fdd_fdi.c fdd_imd.c fdd_img.c fdd_pcjs.c - fdd_mfm.c fdd_td0.c) +add_library(fdd OBJECT + fdd.c + fdc.c + fdc_magitronic.c + fdc_monster.c + fdc_pii15xb.c + fdi2raw.c + fdd_common.c + fdd_86f.c + fdd_fdi.c + fdd_imd.c + fdd_img.c + fdd_pcjs.c + fdd_mfm.c + fdd_td0.c +) + +add_subdirectory(lzw) +target_link_libraries(86Box lzw) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 1a0aa2f102..0c18f2f306 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -77,7 +77,7 @@ int lastbyte = 0; int floppymodified[4]; int floppyrate[4]; -int fdc_type = 0; +int fdc_current[FDC_MAX] = { 0, 0 }; #ifdef ENABLE_FDC_LOG int fdc_do_log = ENABLE_FDC_LOG; @@ -97,51 +97,21 @@ fdc_log(const char *fmt, ...) # define fdc_log(fmt, ...) #endif -#if 0 -const device_t fdc_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; -#endif - -const device_t fdc_internal_device = { - .name = "Internal", - .internal_name = "internal", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - typedef const struct { const device_t *device; } fdc_cards_t; static fdc_cards_t fdc_cards[] = { // clang-format off -#if 0 - { &fdc_none_device }, -#endif - { &fdc_internal_device }, - { &fdc_b215_device }, - { &fdc_pii151b_device }, - { &fdc_pii158b_device }, - { &fdc_monster_device }, - { NULL } + { &device_none }, + { &device_internal }, + { &fdc_xt_device }, + { &fdc_at_device }, + { &fdc_b215_device }, + { &fdc_pii151b_device }, + { &fdc_pii158b_device }, + { &fdc_monster_device }, + { NULL } // clang-format on }; @@ -192,8 +162,8 @@ fdc_card_get_from_internal_name(char *s) void fdc_card_init(void) { - if ((fdc_type > 0) && fdc_cards[fdc_type].device) - device_add(fdc_cards[fdc_type].device); + if ((fdc_current[0] > FDC_INTERNAL) && fdc_cards[fdc_current[0]].device) + device_add_inst(fdc_cards[fdc_current[0]].device, 0); } uint8_t @@ -591,9 +561,6 @@ static void fdc_rate(fdc_t *fdc, int drive) { fdc_update_rate(fdc, drive); -#if 0 - fdc_log("FDD %c: Setting rate: %i, %i, %i (%i, %i)\n", 0x41 + drive, fdc->drvrate[drive], fdc->rate, fdc_get_densel(fdc, drive), fdc->rwc[drive], fdc->densel_force); -#endif fdc_log("FDD %c: [%i] Setting rate: %i, %i, %i (%i, %i, %i)\n", 0x41 + drive, fdc->enh_mode, fdc->drvrate[drive], fdc->rate, fdc_get_densel(fdc, drive), fdc->rwc[drive], fdc->densel_force, fdc->densel_polarity); fdd_set_densel(fdc_get_densel(fdc, drive)); fdc_log("FDD %c: [%i] Densel: %i\n", 0x41 + drive, fdc->enh_mode, fdc_get_densel(fdc, drive)); @@ -626,17 +593,6 @@ fdc_bad_command(fdc_t *fdc) static void fdc_io_command_phase1(fdc_t *fdc, int out) { -#if 0 - int i; - - pclog_toggle_suppr(); - pclog("%02X ", fdc->processed_cmd); - for (i = 0; i < fdc->pnum; i++) - pclog("%02X ", fdc->params[i]); - pclog("\n"); - pclog_toggle_suppr(); -#endif - fifo_reset(fdc->fifo_p); fdc_rate(fdc, fdc->drive); fdc->head = fdc->params[2]; @@ -656,9 +612,11 @@ fdc_io_command_phase1(fdc_t *fdc, int out) ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); fdc->stat = out ? 0x10 : 0x50; - if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) + if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) { fdc->stat |= 0x20; - else + if (out) + fdc->stat |= 0x80; + } else dma_set_drq(fdc->dma_ch, 1); } @@ -931,6 +889,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->format_state = 0; break; case 0x0e: /*Dump registers*/ + if (fdc->flags & FDC_FLAG_NEC) { + fdc_bad_command(fdc); + break; + } fdc->lastdrive = fdc->drive; fdc->interrupt = 0x0e; fdc_callback(fdc); @@ -949,6 +911,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0x10: /*Get version*/ case 0x14: /*Unlock*/ case 0x94: /*Lock*/ + if (fdc->flags & FDC_FLAG_NEC) { + fdc_bad_command(fdc); + break; + } fdc->lastdrive = fdc->drive; fdc->interrupt = fdc->command; fdc_callback(fdc); @@ -962,6 +928,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc_bad_command(fdc); break; case 0x13: /*Configure*/ + if (fdc->flags & FDC_FLAG_NEC) { + fdc_bad_command(fdc); + break; + } fdc->pnum = 0; fdc->ptot = 3; fdc->stat |= 0x90; @@ -1143,9 +1113,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->stat = (1 << fdc->drive); if (!(fdc->flags & FDC_FLAG_PCJR)) fdc->stat |= 0x80; -#if 0 - fdc->head = (fdc->params[0] & 4) ? 1 : 0; -#endif fdc->head = 0; /* TODO: See if this is correct. */ fdc->st0 = fdc->params[0] & 0x03; fdc->st0 |= (fdc->params[0] & 4); @@ -1436,7 +1403,6 @@ fdc_read(uint16_t addr, void *priv) default: ret = 0xFF; } - // fdc_log("Read FDC %04X %02X\n", addr, ret); fdc_log("[%04X:%08X] Read FDC %04X %02X [%i:%02X]\n", CS, cpu_state.pc, addr, ret, drive, fdc->dor & (0x10 << drive)); return ret; } @@ -1646,8 +1612,10 @@ fdc_callback(void *priv) if (fdc->sector == fdc->params[5]) { /* Reached end of track, MT bit is clear */ if (!(fdc->command & 0x80)) { - fdc->rw_track++; - fdc->sector = 1; + if (fdc->dma) { + fdc->rw_track++; + fdc->sector = 1; + } if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) fdc_no_dma_end(fdc, compare); else @@ -1656,10 +1624,12 @@ fdc_callback(void *priv) } /* Reached end of track, MT bit is set, head is 1 */ if (fdd_get_head(real_drive(fdc, fdc->drive)) == 1) { - fdc->rw_track++; - fdc->sector = 1; - fdc->head &= 0xFE; - fdd_set_head(real_drive(fdc, fdc->drive), 0); + if (fdc->dma) { + fdc->rw_track++; + fdc->sector = 1; + fdc->head &= 0xFE; + fdd_set_head(real_drive(fdc, fdc->drive), 0); + } if (!(fdc->flags & FDC_FLAG_PCJR) && fdc->dma && (old_sector == 255)) fdc_no_dma_end(fdc, compare); else @@ -1677,6 +1647,8 @@ fdc_callback(void *priv) } } else if (fdc->sector < fdc->params[5]) fdc->sector++; + else if (fdc->params[5] == 0) + fdc->sector++; ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1); switch (fdc->interrupt) { case 5: @@ -1829,7 +1801,6 @@ void fdc_error(fdc_t *fdc, int st5, int st6) { dma_set_drq(fdc->dma_ch, 0); -#if 1 timer_disable(&fdc->timer); fdc_int(fdc, 1); @@ -1841,6 +1812,10 @@ fdc_error(fdc_t *fdc, int st5, int st6) fdc->st0 |= 0x08; fdc->res[5] = st5; fdc->res[6] = st6; + if (fdc->wrong_am) { + fdc->res[6] |= 0x40; + fdc->wrong_am = 0; + } fdc_log("FDC Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); switch (fdc->interrupt) { case 0x02: @@ -1866,48 +1841,6 @@ fdc_error(fdc_t *fdc, int st5, int st6) } ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); fdc->paramstogo = 7; -#else - switch (fdc->interrupt) { - case 0x02: - case 0x05: - case 0x06: - case 0x09: - case 0x0C: - case 0x11: - case 0x16: - case 0x19: - case 0x1D: - fdc->error = 1; - fdc->st5 = st5; - fdc->st6 = st6; - fdc->tc = 1; - fdc->stat = 0x10; - fdc_callback(fdc); - break; - default: - timer_disable(&fdc->timer); - - fdc_int(fdc, 1); - if (!(fdc->flags & FDC_FLAG_PS1)) - fdc->fintr = 0; - fdc->stat = 0xD0; - fdc->st0 = fdc->res[4] = 0x40 | (fdd_get_head(real_drive(fdc, fdc->drive)) ? 4 : 0) | fdc->rw_drive; - if (fdc->head && !fdd_is_double_sided(real_drive(fdc, fdc->drive))) - fdc->st0 |= 0x08; - fdc->res[5] = st5; - fdc->res[6] = st6; - fdc_log("FDC Error: %02X %02X %02X\n", fdc->res[4], fdc->res[5], fdc->res[6]); - - fdc->res[7] = 0; - fdc->res[8] = 0; - fdc->res[9] = 0; - fdc->res[10] = 0; - - ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0); - fdc->paramstogo = 7; - break; - } -#endif } void @@ -2682,7 +2615,7 @@ const device_t fdc_dp8473_device = { .name = "NS DP8473 Floppy Drive Controller", .internal_name = "fdc_dp8473", .flags = 0, - .local = FDC_FLAG_AT | FDC_FLAG_NSC, + .local = FDC_FLAG_AT | FDC_FLAG_NEC | FDC_FLAG_NO_DSR_RESET, .init = fdc_init, .close = fdc_close, .reset = fdc_reset, diff --git a/src/floppy/fdc_monster.c b/src/floppy/fdc_monster.c index 1629ac1c46..504254ee0c 100644 --- a/src/floppy/fdc_monster.c +++ b/src/floppy/fdc_monster.c @@ -11,10 +11,11 @@ * * * Authors: Jasmine Iwanek, + * Miran Grca, * - * Copyright 2022 Jasmine Iwanek. + * Copyright 2022-2024 Jasmine Iwanek. + * Copyright 2024 Miran Grca. */ - #include #include #include @@ -26,6 +27,8 @@ #include <86box/device.h> #include <86box/io.h> #include <86box/mem.h> +#include <86box/timer.h> +#include <86box/nvr.h> #include <86box/rom.h> #include <86box/machine.h> #include <86box/timer.h> @@ -41,13 +44,73 @@ typedef struct monster_fdc_t { rom_t bios_rom; fdc_t *fdc_pri; fdc_t *fdc_sec; + char nvr_path[64]; } monster_fdc_t; +static void +rom_write(uint32_t addr, uint8_t val, void *priv) +{ + const rom_t *rom = (rom_t *) priv; + +#ifdef ROM_TRACE + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: read byte from BIOS at %06lX\n", addr); +#endif + + if (addr < rom->mapping.base) + return; + if (addr >= (rom->mapping.base + rom->sz)) + return; + rom->rom[(addr - rom->mapping.base) & rom->mask] = val; +} + +static void +rom_writew(uint32_t addr, uint16_t val, void *priv) +{ + rom_t *rom = (rom_t *) priv; + +#ifdef ROM_TRACE + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: read word from BIOS at %06lX\n", addr); +#endif + + if (addr < (rom->mapping.base - 1)) + return; + if (addr >= (rom->mapping.base + rom->sz)) + return; + *(uint16_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val; +} + +static void +rom_writel(uint32_t addr, uint32_t val, void *priv) +{ + rom_t *rom = (rom_t *) priv; + +#ifdef ROM_TRACE + if (rom->mapping.base == ROM_TRACE) + rom_log("ROM: read long from BIOS at %06lX\n", addr); +#endif + + if (addr < (rom->mapping.base - 3)) + return; + if (addr >= (rom->mapping.base + rom->sz)) + return; + *(uint32_t *) &rom->rom[(addr - rom->mapping.base) & rom->mask] = val; +} + static void monster_fdc_close(void *priv) { monster_fdc_t *dev = (monster_fdc_t *) priv; + if (dev->nvr_path[0] != 0x00) { + FILE *fp = nvr_fopen(dev->nvr_path, "wb"); + if (fp != NULL) { + fwrite(dev->bios_rom.rom, 1, 0x2000, fp); + fclose(fp); + } + } + free(dev); } @@ -56,8 +119,7 @@ monster_fdc_init(UNUSED(const device_t *info)) { monster_fdc_t *dev; - dev = (monster_fdc_t *) malloc(sizeof(monster_fdc_t)); - memset(dev, 0, sizeof(monster_fdc_t)); + dev = (monster_fdc_t *) calloc(1, sizeof(monster_fdc_t)); #if 0 uint8_t sec_irq = device_get_config_int("sec_irq"); @@ -79,9 +141,16 @@ monster_fdc_init(UNUSED(const device_t *info)) fdc_set_dma_ch(dev->fdc_sec, sec_dma); #endif -#if 0 uint8_t rom_writes_enabled = device_get_config_int("rom_writes_enabled"); -#endif + if (rom_writes_enabled) { + mem_mapping_set_write_handler(&dev->bios_rom.mapping, rom_write, rom_writew, rom_writel); + sprintf(dev->nvr_path, "monster_fdc_%i.nvr", device_get_instance()); + FILE *fp = nvr_fopen(dev->nvr_path, "rb"); + if (fp != NULL) { + (void) !fread(dev->bios_rom.rom, 1, 0x2000, fp); + fclose(fp); + } + } return dev; } @@ -197,6 +266,7 @@ static const device_config_t monster_fdc_config[] = { { .description = "" } } }, +#endif { .name = "rom_writes_enabled", .description = "Enable BIOS extension ROM Writes", @@ -204,7 +274,6 @@ static const device_config_t monster_fdc_config[] = { .default_string = "", .default_int = 0 }, -#endif { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 72d6ac6485..81edcc8b81 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -104,7 +104,7 @@ static const struct void (*close)(int drive); int size; } loaders[] = { - {"001", img_load, img_close, -1}, + { "001", img_load, img_close, -1}, { "002", img_load, img_close, -1}, { "003", img_load, img_close, -1}, { "004", img_load, img_close, -1}, @@ -139,59 +139,46 @@ static const struct { 0, 0, 0, 0 } }; -static const struct -{ +static const struct { int max_track; int flags; const char *name; const char *internal_name; -} drive_types[] = -{ - { /*None*/ - 0, 0, "None", "none" - }, - { /*5.25" 1DD*/ - 43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd" - }, - { /*5.25" DD*/ - 43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd" - }, - { /*5.25" QD*/ - 86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd" - }, - { /*5.25" HD PS/2*/ - 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "5.25\" 1.2M PS/2", "525_2hd_ps2" - }, - { /*5.25" HD*/ - 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M", "525_2hd" - }, - { /*5.25" HD Dual RPM*/ - 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm" - }, - { /*3.5" 1DD*/ - 86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd" - }, - { /*3.5" DD*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd" - }, - { /*3.5" HD PS/2*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "3.5\" 1.44M PS/2", "35_2hd_ps2" - }, - { /*3.5" HD*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M", "35_2hd" - }, - { /*3.5" HD PC-98*/ - 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec" - }, - { /*3.5" HD 3-Mode*/ - 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode" - }, - { /*3.5" ED*/ - 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed" - }, - { /*End of list*/ - -1, -1, "", "" - } +} drive_types[] = { + /* None */ + { 0, 0, "None", "none" }, + /* 5.25" 1DD */ + { 43, FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0, "5.25\" 180k", "525_1dd" }, + /* 5.25" DD */ + { 43, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0, "5.25\" 360k", "525_2dd" }, + /* 5.25" QD */ + { 86, FLAG_RPM_300 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "5.25\" 720k", "525_2qd" }, + /* 5.25" HD PS/2 */ + { 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "5.25\" 1.2M PS/2", "525_2hd_ps2" }, + /* 5.25" HD */ + { 86, FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M", "525_2hd" }, + /* 5.25" HD Dual RPM */ + { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "5.25\" 1.2M 300/360 RPM", "525_2hd_dualrpm" }, + /* 3.5" 1DD */ + { 86, FLAG_RPM_300 | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 360k", "35_1dd" }, + /* 3.5" DD, Equivalent to TEAC FD-235F */ + { 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_DOUBLE_STEP, "3.5\" 720k", "35_2dd" }, + /* 3.5" HD PS/2 */ + { 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL | FLAG_PS2, "3.5\" 1.44M PS/2", "35_2hd_ps2" }, + /* 3.5" HD, Equivalent to TEAC FD-235HF */ + { 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M", "35_2hd" }, + /* TODO: 3.5" DD, Equivalent to TEAC FD-235GF */ +// { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.25M", "35_2hd_2mode" }, + /* 3.5" HD PC-98 */ + { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP | FLAG_INVERT_DENSEL, "3.5\" 1.25M PC-98", "35_2hd_nec" }, + /* 3.5" HD 3-Mode, Equivalent to TEAC FD-235HG */ + { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP, "3.5\" 1.44M 300/360 RPM", "35_2hd_3mode" }, + /* 3.5" ED, Equivalent to TEAC FD-235J */ + { 86, FLAG_RPM_300 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M", "35_2ed" }, + /* 3.5" ED Dual RPM, Equivalent to TEAC FD-335J */ + { 86, FLAG_RPM_300 | FLAG_RPM_360 | FLAG_DS | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2 | FLAG_DOUBLE_STEP, "3.5\" 2.88M 300/360 RPM", "35_2ed_dualrpm" }, + /* End of list */ + { -1, -1, "", "" } }; #ifdef ENABLE_FDD_LOG diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index fa1c070f15..cf9e836943 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -628,10 +628,12 @@ d86f_get_array_size(int drive, int side, int words) int hole; int rm; int ssd; + int mpc; rm = d86f_get_rpm_mode(drive); ssd = d86f_get_speed_shift_dir(drive); - hole = (d86f_handler[drive].disk_flags(drive) & 6) >> 1; + hole = (d86f_handler[drive].disk_flags(drive) >> 1) & 3; + mpc = (d86f_handler[drive].disk_flags(drive) >> 13) & 1; if (!rm && ssd) /* Special case - extra bit cells size specifies entire array size. */ array_size = 0; @@ -703,13 +705,20 @@ d86f_get_array_size(int drive, int side, int words) array_size <<= 4; array_size += d86f_handler[drive].extra_bit_cells(drive, side); - if (array_size & 15) - array_size = (array_size >> 4) + 1; - else - array_size = (array_size >> 4); + if (mpc && !words) { + if (array_size & 7) + array_size = (array_size >> 3) + 1; + else + array_size = (array_size >> 3); + } else { + if (array_size & 15) + array_size = (array_size >> 4) + 1; + else + array_size = (array_size >> 4); - if (!words) - array_size <<= 1; + if (!words) + array_size <<= 1; + } return array_size; } @@ -1098,9 +1107,9 @@ d86f_get_bit(int drive, int side) /* In some cases, misindentification occurs so we need to make sure the surface data array is not not NULL. */ if (d86f_has_surface_desc(drive) && dev->track_surface_data[side]) { - if (d86f_reverse_bytes(drive)) { + if (d86f_reverse_bytes(drive)) surface_data = dev->track_surface_data[side][track_word] & 0xFF; - } else { + else { surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; surface_data |= (dev->track_surface_data[side][track_word] >> 8); } @@ -1150,9 +1159,9 @@ d86f_put_bit(int drive, int side, int bit) } if (d86f_has_surface_desc(drive)) { - if (d86f_reverse_bytes(drive)) { + if (d86f_reverse_bytes(drive)) surface_data = dev->track_surface_data[side][track_word] & 0xFF; - } else { + else { surface_data = (dev->track_surface_data[side][track_word] & 0xFF) << 8; surface_data |= (dev->track_surface_data[side][track_word] >> 8); } @@ -1177,9 +1186,9 @@ d86f_put_bit(int drive, int side, int bit) surface_data &= ~(1 << track_bit); surface_data |= (surface_bit << track_bit); - if (d86f_reverse_bytes(drive)) { + if (d86f_reverse_bytes(drive)) dev->track_surface_data[side][track_word] = surface_data; - } else { + else { dev->track_surface_data[side][track_word] = (surface_data & 0xFF) << 8; dev->track_surface_data[side][track_word] |= (surface_data >> 8); } @@ -1191,9 +1200,9 @@ d86f_put_bit(int drive, int side, int bit) encoded_data &= ~(1 << track_bit); encoded_data |= (current_bit << track_bit); - if (d86f_reverse_bytes(drive)) { + if (d86f_reverse_bytes(drive)) d86f_handler[drive].encoded_data(drive, side)[track_word] = encoded_data; - } else { + else { d86f_handler[drive].encoded_data(drive, side)[track_word] = (encoded_data & 0xFF) << 8; d86f_handler[drive].encoded_data(drive, side)[track_word] |= (encoded_data >> 8); } @@ -1298,7 +1307,16 @@ d86f_find_address_mark_fm(int drive, int side, find_t *find, uint16_t req_am, ui find->sync_pos = 0xFFFFFFFF; if (ignore_other_am & 1) { /* Skip mode, let's go back to finding ID. */ - dev->state -= 2; + fdc_set_wrong_am(d86f_fdc); + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + if (dev->state == STATE_02_READ_DATA) + fdc_track_finishread(d86f_fdc, dev->error_condition); + else if (dev->state == STATE_11_SCAN_DATA) + fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); + else + fdc_sector_finishread(d86f_fdc); } else { /* Not skip mode, process the sector anyway. */ fdc_set_wrong_am(d86f_fdc); @@ -1377,7 +1395,16 @@ d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_am, u find->sync_pos = 0xFFFFFFFF; if (ignore_other_am & 1) { /* Skip mode, let's go back to finding ID. */ - dev->state -= 2; + fdc_set_wrong_am(d86f_fdc); + dev->data_find.sync_marks = dev->data_find.bits_obtained = dev->data_find.bytes_obtained = 0; + dev->error_condition = 0; + dev->state = STATE_IDLE; + if (dev->state == STATE_02_READ_DATA) + fdc_track_finishread(d86f_fdc, dev->error_condition); + else if (dev->state == STATE_11_SCAN_DATA) + fdc_sector_finishcompare(d86f_fdc, (dev->satisfying_bytes == ((128 << ((uint32_t) dev->last_sector.id.n)) - 1)) ? 1 : 0); + else + fdc_sector_finishread(d86f_fdc); } else { /* Not skip mode, process the sector anyway. */ fdc_set_wrong_am(d86f_fdc); @@ -1815,7 +1842,6 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 uint16_t mask_data; uint16_t mask_surface; uint16_t mask_hole; - uint16_t mask_fuzzy; decoded_t dbyte; decoded_t dpbyte; @@ -1828,6 +1854,7 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 if (type == 0) { /* Byte write. */ encoded_byte = d86f_encode_byte(drive, 0, dbyte, dpbyte); + dev->preceding_bit[side] = encoded_byte & 1; if (!d86f_reverse_bytes(drive)) { mask_data = encoded_byte >> 8; encoded_byte &= 0xFF; @@ -1837,6 +1864,7 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 } else { /* Word write. */ encoded_byte = byte; + dev->preceding_bit[side] = (encoded_byte >> 8) & 1; if (d86f_reverse_bytes(drive)) { mask_data = encoded_byte >> 8; encoded_byte &= 0xFF; @@ -1845,16 +1873,19 @@ d86f_write_direct_common(int drive, int side, uint16_t byte, uint8_t type, uint3 } } - dev->preceding_bit[side] = encoded_byte & 1; - if (d86f_has_surface_desc(drive)) { - mask_data = dev->track_encoded_data[side][pos] ^= 0xFFFF; + /* Inverted track data, clear bits are now set. */ + mask_data = ~dev->track_encoded_data[side][pos]; + /* Surface data. */ mask_surface = dev->track_surface_data[side][pos]; - mask_hole = (mask_surface & mask_data) ^ 0xFFFF; /* This will retain bits that are both fuzzy and 0, therefore physical holes. */ - encoded_byte &= mask_hole; /* Filter out physical hole bits from the encoded data. */ - mask_data ^= 0xFFFF; /* Invert back so bits 1 are 1 again. */ - mask_fuzzy = (mask_surface & mask_data) ^ 0xFFFF; /* All fuzzy bits are 0. */ - dev->track_surface_data[side][pos] &= mask_fuzzy; /* Remove fuzzy bits (but not hole bits) from the surface mask, making them regular again. */ + + /* Hole = surface & ~data, so holes are one. */ + mask_hole = mask_surface & mask_data; + /* Hole bits are ones again, set the surface data to that. */ + dev->track_surface_data[side][pos] = mask_hole; + + /* Force the data of any hole to zero. */ + encoded_byte &= ~mask_hole; } dev->track_encoded_data[side][pos] = encoded_byte; @@ -2847,22 +2878,22 @@ d86f_construct_encoded_buffer(int drive, int side) /* Source image has surface description data, so we have some more handling to do. */ src1_fuzm = src1[i] & src1_s[i]; src2_fuzm = src2[i] & src2_s[i]; - dst_fuzm = src1_fuzm | src2_fuzm; /* The bits that remain set are fuzzy in either one or - the other or both. */ - src1_holm = src1[i] | (src1_s[i] ^ 0xffff); - src2_holm = src2[i] | (src2_s[i] ^ 0xffff); - dst_holm = (src1_holm & src2_holm) ^ 0xffff; /* The bits that remain set are holes in both. */ - dst_neim = (dst_fuzm | dst_holm) ^ 0xffff; /* The bits that remain set are those that are neither - fuzzy nor are holes in both. */ + dst_fuzm = src1_fuzm | src2_fuzm; /* The bits that remain set are fuzzy in either one or + the other or both. */ + src1_holm = ~src1[i] & src1_s[i]; + src2_holm = ~src2[i] & src2_s[i]; + dst_holm = src1_holm & src2_holm; /* The bits that remain set are holes in both. */ + dst_neim = ~(dst_fuzm | dst_holm); /* The bits that remain set are those that are neither + fuzzy nor are holes in both. */ src1_d = src1[i] & dst_neim; src2_d = src2[i] & dst_neim; - dst_s[i] = (dst_neim ^ 0xffff); /* The set bits are those that are either fuzzy or are - holes in both. */ - dst[i] = (src1_d | src2_d); /* Initial data is remaining data from Source 1 and - Source 2. */ - dst[i] |= dst_fuzm; /* Add to it the fuzzy bytes (holes have surface bit set - but data bit clear). */ + dst_s[i] = ~dst_neim; /* The set bits are those that are either fuzzy or are + holes in both. */ + dst[i] = (src1_d | src2_d); /* Initial data is remaining data from Source 1 and + Source 2. */ + dst[i] |= dst_fuzm; /* Add to it the fuzzy bytes (holes have surface bit set + but data bit clear). */ } else { /* No surface data, the handling is much simpler - a simple OR. */ dst[i] = src1[i] | src2[i]; @@ -2891,15 +2922,14 @@ d86f_decompose_encoded_buffer(int drive, int side) if (d86f_has_surface_desc(drive)) { /* Source image has surface description data, so we have some more handling to do. We need hole masks for both buffers. Holes have data bit clear and surface bit set. */ - temp = src1[i] & (src1_s[i] ^ 0xffff); - temp2 = src2[i] & (src2_s[i] ^ 0xffff); - src1[i] = dst[i] & temp; - src1_s[i] = temp ^ 0xffff; - src2[i] = dst[i] & temp2; - src2_s[i] = temp2 ^ 0xffff; - } else { + temp = ~src1[i] & src1_s[i]; + temp2 = ~src2[i] & src2_s[i]; + src1[i] = dst[i] & ~temp; + src1_s[i] = temp; + src2[i] = dst[i] & ~temp2; + src2_s[i] = temp2; + } else src1[i] = src2[i] = dst[i]; - } } } @@ -3195,6 +3225,8 @@ d86f_writeback(int drive) free(dev->filebuf); } #endif + + fflush(dev->fp); } void @@ -3526,9 +3558,9 @@ d86f_load(int drive, char *fn) writeprot[drive] = 1; } - if (ui_writeprot[drive]) { + if (ui_writeprot[drive]) writeprot[drive] = 1; - } + fwriteprot[drive] = writeprot[drive]; fseek(dev->fp, 0, SEEK_END); diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index a5cd8f056f..0839c29001 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -45,6 +45,7 @@ typedef struct imd_track_t { uint32_t gap3_len; uint16_t side_flags; uint8_t max_sector_size; + uint8_t spt; } imd_track_t; typedef struct imd_t { @@ -548,6 +549,8 @@ imd_writeback(int drive) } } } + + fflush(dev->fp); } static uint8_t @@ -711,6 +714,9 @@ imd_load(int drive, char *fn) imd[drive] = dev; while (1) { + imd_log("In : %02X %02X %02X %02X %02X\n", + buffer2[0], buffer2[1], buffer2[2], buffer2[3], buffer2[4]); + track = buffer2[1]; side = buffer2[2]; if (side & 1) @@ -718,16 +724,20 @@ imd_load(int drive, char *fn) extra = side & 0xC0; side &= 0x3F; + track_spt = buffer2[3]; + dev->tracks[track][side].spt = track_spt; + sector_size = buffer2[4]; + dev->tracks[track][side].side_flags = (buffer2[0] % 3); - if (!dev->tracks[track][side].side_flags) + if ((track_spt != 0x00) && (!dev->tracks[track][side].side_flags)) dev->disk_flags |= 0x02; - dev->tracks[track][side].side_flags |= (!(buffer2[0] - dev->tracks[track][side].side_flags) ? 0 : 8); + dev->tracks[track][side].side_flags |= + (!(buffer2[0] - dev->tracks[track][side].side_flags) ? 0 : 8); mfm = dev->tracks[track][side].side_flags & 8; track_total = mfm ? 146 : 73; pre_sector = mfm ? 60 : 42; - track_spt = buffer2[3]; - sector_size = buffer2[4]; + imd_log("Out : %02X %02X %02X %02X %02X\n", buffer2[0], track, side, track_spt, sector_size); if ((track_spt == 15) && (sector_size == 2)) dev->tracks[track][side].side_flags |= 0x20; if ((track_spt == 16) && (sector_size == 2)) @@ -744,7 +754,7 @@ imd_load(int drive, char *fn) dev->tracks[track][side].max_sector_size = 5; if (!mfm) dev->tracks[track][side].max_sector_size--; - imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track][side].side_flags); + imd_log("Side flags for (%02i)(%01i): %02X\n", track, side, dev->tracks[track] [side].side_flags); dev->tracks[track][side].is_present = 1; dev->tracks[track][side].file_offs = (buffer2 - buffer); memcpy(dev->tracks[track][side].params, buffer2, 5); @@ -762,7 +772,6 @@ imd_load(int drive, char *fn) } if (track_spt == 0x00) { - dev->tracks[track][side].n_map_offs = last_offset; buffer2 = buffer + last_offset; last_offset += track_spt; dev->tracks[track][side].is_present = 0; @@ -872,7 +881,7 @@ imd_load(int drive, char *fn) } dev->tracks[track][side].gap3_len = (size_diff - minimum_gap4) / track_spt; - } else if ((track_spt == 0x00) || (gap3_sizes[converted_rate][sector_size][track_spt] != 0x00)) + } else dev->tracks[track][side].gap3_len = gap3_sizes[converted_rate][sector_size][track_spt]; /* imd_log("GAP3 length for (%02i)(%01i): %i bytes\n", track, side, dev->tracks[track][side].gap3_len); */ @@ -886,6 +895,32 @@ imd_load(int drive, char *fn) /* If more than 43 tracks, then the tracks are thin (96 tpi). */ dev->track_count++; + imd_log("In : dev->track_count = %i\n", dev->track_count); + + int empty_tracks = 0; + for (int i = 0; i < dev->track_count; i++) { + if ((dev->sides == 2) && (dev->tracks[i][0].spt == 0x00) && (dev->tracks[i][1].spt == 0x00)) + empty_tracks++; + else if ((dev->sides == 1) && (dev->tracks[i][0].spt == 0x00)) + empty_tracks++; + } + imd_log("empty_tracks = %i\n", empty_tracks); + + if (empty_tracks >= (dev->track_count >> 1)) { + for (int i = 0; i < dev->track_count; i += 2) { + imd_log("Thick %02X = Thin %02X\n", i >> 1, i); + dev->tracks[i >> 1][0] = dev->tracks[i][0]; + dev->tracks[i >> 1][1] = dev->tracks[i][1]; + } + for (int i = (dev->track_count >> 1); i < dev->track_count; i++) { + imd_log("Emptying %02X....\n", i); + memset(&(dev->tracks[i][0]), 1, sizeof(imd_track_t)); + memset(&(dev->tracks[i][1]), 1, sizeof(imd_track_t)); + } + dev->track_count >>= 1; + } + imd_log("Out: dev->track_count = %i\n", dev->track_count); + dev->track_width = 0; if (dev->track_count > 43) dev->track_width = 1; diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 404cbf9fae..62b05a9446 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -431,6 +431,8 @@ write_back(int drive) if (fwrite(dev->track_data[side], 1, size, dev->fp) != size) fatal("IMG write_back(): Error writing data\n"); } + + fflush(dev->fp); } static uint16_t diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index b4c859d5d8..a332d25c9b 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -454,9 +454,12 @@ mfm_load(int drive, char *fn) dev->br_rounded = (int) dbr; mfm_log("Rounded bit rate: %i kbps\n", dev->br_rounded); - dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0; + if (dev->hdr.rpm != 0) + dbr = round(((double) dev->hdr.rpm) / 60.0) * 60.0; + else + dbr = (dev->br_rounded == 300) ? 360.0 : 300.0; dev->rpm_rounded = (int) dbr; - mfm_log("Rounded RPM: %i kbps\n", dev->rpm_rounded); + mfm_log("Rounded RPM: %i rpm\n", dev->rpm_rounded); } /* Set up the drive unit. */ diff --git a/src/floppy/fdd_pcjs.c b/src/floppy/fdd_pcjs.c index 474d8ee372..b7b3cc69d1 100644 --- a/src/floppy/fdd_pcjs.c +++ b/src/floppy/fdd_pcjs.c @@ -276,7 +276,7 @@ int json_parse(pcjs_t *dev) } /* Read and null terminate */ - fread(buffer, sizeof(char), numbytes, dev->fp); + (void) !fread(buffer, sizeof(char), numbytes, dev->fp); buffer[numbytes] = '\0'; cJSON *parsed_json = cJSON_Parse(buffer); @@ -305,7 +305,6 @@ int json_parse(pcjs_t *dev) const cJSON *each_track = NULL; int total_c = 0; - int full_count = 0; /* The diskData array is essentially [c][h][s] */ /* Start with the tracks in [c] */ @@ -350,7 +349,7 @@ int json_parse(pcjs_t *dev) if (sector->data == NULL ) { /* We could verify the sector size against the metadata here */ - sector->data = (uint8 *)calloc(1, current_length); + sector->data = (uint8_t *)calloc(1, current_length); if (sector->data == NULL ) { pcjs_log("Failed to allocate\n"); pcjs_error = E_ALLOC; @@ -422,7 +421,6 @@ int json_parse(pcjs_t *dev) } total_sectors++; - full_count++; dev->calc_total_sectors = total_sectors; /* End sectors */ } diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index 46e29343be..0bf4b1c714 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -42,6 +42,7 @@ #include <86box/fdd_86f.h> #include <86box/fdd_td0.h> #include <86box/fdc.h> +#include "lzw/lzw.h" #define BUFSZ 512 /* new input buffer */ #define TD0_MAX_BUFSZ (1024UL * 1024UL * 4UL) @@ -124,7 +125,9 @@ typedef struct td0_t { uint8_t xdf_ordered_pos[256][2]; uint8_t interleave_ordered_pos[256][2]; + uint8_t *lzw_buf; uint8_t *imagebuf; + uint8_t *processed_buf; } td0_t; @@ -650,11 +653,20 @@ td0_initialize(int drive) head_count = header[9]; if (header[0] == 't') { - td0_log("TD0: File is compressed\n"); - disk_decode.fdd_file = dev->fp; - state_init_Decode(&disk_decode); - disk_decode.fdd_file_offset = 12; - state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); + if (((header[4] / 10) % 10) == 2) { + td0_log("TD0: File is compressed (TeleDisk 2.x, LZHUF)\n"); + disk_decode.fdd_file = dev->fp; + state_init_Decode(&disk_decode); + disk_decode.fdd_file_offset = 12; + state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); + } else { + td0_log("TD0: File is compressed (TeleDisk 1.x, LZW)\n"); + if (fseek(dev->fp, 12, SEEK_SET) == -1) + fatal("td0_initialize(): Error seeking to offet 12\n"); + if (fread(dev->lzw_buf, 1, file_size - 12, dev->fp) != (file_size - 12)) + fatal("td0_initialize(): Error reading LZW-encoded buffer\n"); + LZWDecodeFile((char *) dev->imagebuf, (char *) dev->lzw_buf, NULL, file_size - 12); + } } else { td0_log("TD0: File is uncompressed\n"); if (fseek(dev->fp, 12, SEEK_SET) == -1) @@ -1224,10 +1236,9 @@ td0_load(int drive, char *fn) /* Allocate the processing buffers. */ i = 1024UL * 1024UL * 4UL; - dev->imagebuf = (uint8_t *) malloc(i); - memset(dev->imagebuf, 0x00, i); - dev->processed_buf = (uint8_t *) malloc(i); - memset(dev->processed_buf, 0x00, i); + dev->lzw_buf = (uint8_t *) calloc(1, i); + dev->imagebuf = (uint8_t *) calloc(1, i); + dev->processed_buf = (uint8_t *) calloc(1, i); if (!td0_initialize(drive)) { td0_log("TD0: Failed to initialize\n"); @@ -1268,6 +1279,8 @@ td0_close(int drive) d86f_unregister(drive); + if (dev->lzw_buf) + free(dev->lzw_buf); if (dev->imagebuf) free(dev->imagebuf); if (dev->processed_buf) diff --git a/src/cpu/softfloat/CMakeLists.txt b/src/floppy/lzw/CMakeLists.txt similarity index 68% rename from src/cpu/softfloat/CMakeLists.txt rename to src/floppy/lzw/CMakeLists.txt index 9361571855..bc6f0b6129 100644 --- a/src/cpu/softfloat/CMakeLists.txt +++ b/src/floppy/lzw/CMakeLists.txt @@ -13,5 +13,4 @@ # Copyright 2020-2021 David Hrdlička. # -add_library(softfloat OBJECT f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc softfloat_poly.cc softfloat.cc softfloat16.cc - softfloat-muladd.cc softfloat-round-pack.cc softfloat-specialize.cc softfloatx80.cc) +add_library(lzw STATIC lzwdecode.c lzwencode.c) \ No newline at end of file diff --git a/src/floppy/lzw/lzw.h b/src/floppy/lzw/lzw.h new file mode 100644 index 0000000000..26abbf6ad5 --- /dev/null +++ b/src/floppy/lzw/lzw.h @@ -0,0 +1,49 @@ +/*************************************************************************** +* Header for Lempel-Ziv-Welch Encoding and Decoding Library +* +* File : lzw.h +* Purpose : Provides prototypes for functions that use Lempel-Ziv-Welch +* coding to encode/decode files. +* Author : Michael Dipperstein +* Date : January 30, 2004 +* +**************************************************************************** +* +* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines +* Copyright (C) 2005, 2007, 2014 by +* Michael Dipperstein (mdipperstein@gmail.com) +* +* This file is part of the lzw library. +* +* The lzw library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public License as +* published by the Free Software Foundation; either version 3 of the +* License, or (at your option) any later version. +* +* The lzw library is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +* General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, see . +* +***************************************************************************/ + +#ifndef _LZW_H_ +#define _LZW_H_ + +/*************************************************************************** +* CONSTANTS +***************************************************************************/ + +/*************************************************************************** +* PROTOTYPES +***************************************************************************/ + /* encode inFile */ +int LZWEncodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len); + +/* decode inFile*/ +int LZWDecodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len); + +#endif /* ndef _LZW_H_ */ diff --git a/src/floppy/lzw/lzwdecode.c b/src/floppy/lzw/lzwdecode.c new file mode 100644 index 0000000000..7634b52f87 --- /dev/null +++ b/src/floppy/lzw/lzwdecode.c @@ -0,0 +1,269 @@ +/*************************************************************************** +* Lempel-Ziv-Welch Decoding Functions +* +* File : lzwdecode.c +* Purpose : Provides a function for decoding Lempel-Ziv-Welch encoded +* file streams +* Author : Michael Dipperstein +* Date : January 30, 2005 +* +**************************************************************************** +* +* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines +* Copyright (C) 2005, 2007, 2014, 2017 by +* Michael Dipperstein (mdipperstein@gmail.com) +* +* This file is part of the lzw library. +* +* The lzw library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public License as +* published by the Free Software Foundation; either version 3 of the +* License, or (at your option) any later version. +* +* The lzw library is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +* General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, see . +* +***************************************************************************/ + +/*************************************************************************** +* INCLUDED FILES +***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "lzw.h" +#include "lzwlocal.h" + +/*************************************************************************** +* TYPE DEFINITIONS +***************************************************************************/ +typedef struct +{ + uint8_t suffixChar; /* last char in encoded string */ + uint16_t prefixCode; /* code for remaining chars in string */ +} decode_dictionary_t; + +/*************************************************************************** +* CONSTANTS +***************************************************************************/ + +/*************************************************************************** +* MACROS +***************************************************************************/ + +/*************************************************************************** +* GLOBAL VARIABLES +***************************************************************************/ + +/* dictionary of string the code word is the dictionary index */ +static decode_dictionary_t dictionary[(MAX_CODES - FIRST_CODE)]; + +/*************************************************************************** +* PROTOTYPES +***************************************************************************/ +static uint8_t DecodeRecursive(unsigned int code, char **dest); + +/* read encoded data */ +static int GetCodeWord(char *src); + +static uint16_t bufPos = 0x0000; +static uint16_t bufLen = 0x0000; + +static uint32_t bufOutPos = 0x00000000; + +/*************************************************************************** +* FUNCTIONS +***************************************************************************/ + +/*************************************************************************** +* Function : LZWDecodeFile +* Description: This routine reads an input file 1 encoded string at a +* time and decodes it using the LZW algorithm. +* Parameters : fpIn - pointer to the open binary file to decode +* fpOut - pointer to the open binary file to write decoded +* output +* Effects : fpIn is decoded using the LZW algorithm with CODE_LEN codes +* and written to fpOut. Neither file is closed after exit. +* Returned : 0 for success, -1 for failure. errno will be set in the +* event of a failure. +***************************************************************************/ +int +LZWDecodeFile_Internal(char *dest, char *src) +{ + uint16_t nextCode; /* value of next code */ + uint16_t lastCode; /* last decoded code word */ + int code; /* code word to decode */ + uint8_t c; /* last decoded character */ + + /* validate arguments */ + if (dest == NULL) { + errno = ENOENT; + return -1; + } + + bufPos = 0x0000; + bufOutPos = 0x00000000; + + /* initialize for decoding */ + nextCode = FIRST_CODE; /* code for next (first) string */ + + /* first code from file must be a character. use it for initial values */ + lastCode = GetCodeWord(src); + c = lastCode; + *(dest++) = lastCode; + bufOutPos++; + + /* decode rest of file */ + while ((int)(code = GetCodeWord(src)) != EOF) { + if (code < nextCode) { + /* we have a known code. decode it */ + c = DecodeRecursive(code, &dest); + } else { + /*************************************************************** + * We got a code that's not in our dictionary. This must be due + * to the string + char + string + char + string exception. + * Build the decoded string using the last character + the + * string from the last code. + ***************************************************************/ + unsigned char tmp; + + tmp = c; + c = DecodeRecursive(lastCode, &dest); + *(dest++) = tmp; + bufOutPos++; + } + + /* if room, add new code to the dictionary */ + if (nextCode < MAX_CODES) { + dictionary[nextCode - FIRST_CODE].prefixCode = lastCode; + dictionary[nextCode - FIRST_CODE].suffixChar = c; + nextCode++; + } + + /* save character and code for use in unknown code word case */ + lastCode = code; + } + + return 0; +} + +int +LZWDecodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len) +{ + uint16_t size = 0x0000; + uint64_t pos = 0x0000000000000000ULL; + + /* validate arguments */ + if ((dest == NULL) || (src == NULL)) { + errno = ENOENT; + return -1; + } + + if (dst_len != NULL) + *dst_len = 0x0000000000000000ULL; + + while (1) { + size = *(uint16_t *) src; + src += 2; + bufLen = size; + size >>= 1; + if (bufLen & 1) + size++; + if (size > 0x1800) + return -1; + LZWDecodeFile_Internal(dest, src); + src += size; + dest += bufOutPos; + if (dst_len != NULL) + *dst_len += bufOutPos; + pos += (size + 2); + if ((size < 0x1800) || (pos >= src_len)) + /* We have just decoded a block smaller than 0x3000 bytes, + this means this has been the last block, end. */ + break; + } + + return 0; +} + +/*************************************************************************** +* Function : DecodeRecursive +* Description: This function uses the dictionary to decode a code word +* into the string it represents and write it to the output +* file. The string is actually built in reverse order and +* recursion is used to write it out in the correct order. +* Parameters : code - the code word to decode +* fpOut - the file that the decoded code word is written to +* Effects : Decoded code word is written to a file +* Returned : The first character in the decoded string +***************************************************************************/ +static uint8_t +DecodeRecursive(unsigned int code, char **dest) +{ + unsigned char c; + unsigned char firstChar; + + if (code >= FIRST_CODE) { + /* code word is string + c */ + c = dictionary[code - FIRST_CODE].suffixChar; + code = dictionary[code - FIRST_CODE].prefixCode; + + /* evaluate new code word for remaining string */ + firstChar = DecodeRecursive(code, dest); + } else { + /* code word is just c */ + c = code; + firstChar = code; + } + + *((*dest)++) = c; + bufOutPos++; + return firstChar; +} + +/*************************************************************************** +* Function : GetCodeWord +* Description: This function reads and returns a code word from an +* encoded file. In order to deal with endian issue the +* code word is read least significant byte followed by the +* remaining bits. +* Parameters : fpIn - file containing the encoded data +* codeLen - number of bits in code word +* Effects : code word is read from encoded input +* Returned : The next code word in the encoded file. EOF if the end +* of file has been reached. +* +* NOTE: If the code word contains more than 16 bits, this routine should +* be modified to read in all the bytes from least significant to +* most significant followed by any left over bits. +***************************************************************************/ +static int +GetCodeWord(char *src) +{ + int code = 0; + static unsigned int realPos; + + realPos = bufPos >> 1; + + if (bufPos >= bufLen) + /* End of buffer. */ + code = EOF; + else if (bufPos & 1) + /* Odd position. */ + code = (((uint8_t) src[realPos] & 0xf0) >> 4) | ((uint8_t) src[realPos + 1] << 4); + else + /* Even position. */ + code = ((uint8_t) src[realPos] & 0xff) | (((uint8_t) src[realPos + 1] & 0xf) << 8); + + bufPos += 3; + + return code; +} diff --git a/src/floppy/lzw/lzwencode.c b/src/floppy/lzw/lzwencode.c new file mode 100644 index 0000000000..0a4d659bbc --- /dev/null +++ b/src/floppy/lzw/lzwencode.c @@ -0,0 +1,454 @@ +/*************************************************************************** +* Lempel-Ziv-Welch Encoding Functions +* +* File : lzwencode.c +* Purpose : Provides a function for Lempel-Ziv-Welch encoding of file +* streams +* Author : Michael Dipperstein +* Date : January 30, 2005 +* +**************************************************************************** +* +* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines +* Copyright (C) 2005, 2007, 2014, 2017 by +* Michael Dipperstein (mdipperstein@gmail.com) +* +* This file is part of the lzw library. +* +* The lzw library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public License as +* published by the Free Software Foundation; either version 3 of the +* License, or (at your option) any later version. +* +* The lzw library is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +* General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, see . +* +***************************************************************************/ + +/*************************************************************************** +* INCLUDED FILES +***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "lzw.h" +#include "lzwlocal.h" + +/*************************************************************************** +* TYPE DEFINITIONS +***************************************************************************/ +/* node in dictionary tree */ +typedef struct dict_node_t +{ + unsigned int codeWord; /* code word for this entry */ + unsigned char suffixChar; /* last char in encoded string */ + unsigned int prefixCode; /* code for remaining chars in string */ + + /* pointer to child nodes */ + struct dict_node_t *left; /* child with < key */ + struct dict_node_t *right; /* child with >= key */ +} dict_node_t; + +/*************************************************************************** +* CONSTANTS +***************************************************************************/ + +/*************************************************************************** +* MACROS +***************************************************************************/ + +/*************************************************************************** +* GLOBAL VARIABLES +***************************************************************************/ + +/*************************************************************************** +* PROTOTYPES +***************************************************************************/ + +/* dictionary tree node create/free */ +static dict_node_t *MakeNode(const unsigned int codeWord, const unsigned int prefixCode, + const unsigned char suffixChar); +static void FreeTree(dict_node_t *node); + +/* searches tree for matching dictionary entry */ +static dict_node_t *FindDictionaryEntry(dict_node_t *root, const int unsigned prefixCode, + const unsigned char c); + +/* makes key from prefix code and character */ +static unsigned int MakeKey(const unsigned int prefixCode, const unsigned char suffixChar); + +/* write encoded data */ +static int PutCodeWord(char *dest, int code); + +static char *src_base; +static uint64_t src_length = 0x0000000000000000ULL; + +static uint32_t bufPos = 0x00000000; +static uint32_t bufInPos = 0x00000000; + +static int +is_eob(char *src) +{ + return ((uint64_t) (uintptr_t) (src - src_base)) >= src_length; +} + +static int +get_char(char **src) +{ + int ret = EOF; + + if (!is_eob(*src)) { + ret = (uint8_t) **src; + (*src)++; + } + + return ret; +} + +/*************************************************************************** +* FUNCTIONS +***************************************************************************/ + +static int +LZWEncodeFile_Internal(char *dest, char *src) +{ + unsigned int code; /* code for current string */ + unsigned int nextCode; /* next available code index */ + int c; /* character to add to string */ + + dict_node_t *dictRoot; /* root of dictionary tree */ + dict_node_t *node; /* node of dictionary tree */ + + /* validate arguments */ + if (src == NULL) { + errno = ENOENT; + return -1; + } + + /* initialize dictionary as empty */ + dictRoot = NULL; + + nextCode = FIRST_CODE; /* code for next (first) string */ + + bufPos = 0x00000000; + bufInPos = 0x00000000; + + /* now start the actual encoding process */ + + c = get_char(&src); + + if (c == EOF) + return -1; /* empty file */ + else { + bufInPos++; + code = c; /* start with code string = first character */ + } + + /* create a tree root from 1st 2 character string */ + if ((c = get_char(&src)) != EOF) { + bufInPos++; + + /* special case for NULL root */ + dictRoot = MakeNode(nextCode, code, c); + + if (dictRoot == NULL) { + perror("Making Dictionary Root"); + return -1; + } + + nextCode++; + + /* write code for 1st char */ + (void) PutCodeWord(dest, code); + + /* new code is just 2nd char */ + code = c; + } + + /* now encode normally */ + while ((c = get_char(&src)) != EOF) { + /* look for code + c in the dictionary */ + node = FindDictionaryEntry(dictRoot, code, c); + + if ((node->prefixCode == code) && (node->suffixChar == c)) + /* code + c is in the dictionary, make it's code the new code */ + code = node->codeWord; + else { + /* code + c is not in the dictionary, add it if there's room */ + if (nextCode < MAX_CODES) { + dict_node_t *tmp = MakeNode(nextCode, code, c); + + if (tmp == NULL) { + perror("Making Dictionary Node"); + FreeTree(dictRoot); + return -1; + } + + nextCode++; + + if (MakeKey(code, c) < MakeKey(node->prefixCode, node->suffixChar)) + node->left = tmp; + else + node->right = tmp; + } + + /* write out code for the string before c was added */ + if (PutCodeWord(dest, code)) + break; + + /* new code is just c */ + code = c; + } + + bufInPos++; + } + + /* no more input. write out last of the code. */ + (void) PutCodeWord(dest, code); + + /* free the dictionary */ + FreeTree(dictRoot); + + return (c == EOF) ? 1 : 0; +} + +/*************************************************************************** +* Function : LZWEncodeFile +* Description: This routine reads an input file 1 character at a time and +* writes out an LZW encoded version of that file. +* Parameters : fpIn - pointer to the open binary file to encode +* fpOut - pointer to the open binary file to write encoded +* output +* Effects : fpIn is encoded using the LZW algorithm with CODE_LEN codes +* and written to fpOut. Neither file is closed after exit. +* Returned : 0 for success, -1 for failure. errno will be set in the +* event of a failure. +***************************************************************************/ +int +LZWEncodeFile(char *dest, char *src, uint64_t *dst_len, uint64_t src_len) +{ + uint64_t pos = 0x0000000000000000ULL; + + /* validate arguments */ + if ((dest == NULL) || (src == NULL)) { + errno = ENOENT; + return -1; + } + + if (dst_len != NULL) + *dst_len = 0x0000000000000000ULL; + + src_base = src; + src_length = src_len; + + while (1) { + int ret = LZWEncodeFile_Internal(dest + 2, src); + if (ret == -1) + break; + *(uint16_t *) dest = bufPos; + if (bufPos & 1) + bufPos = (bufPos >> 1) + 1; + else + bufPos >>= 1; + dest += (bufPos + 2); + if (dst_len != NULL) + *dst_len += (bufPos + 2); + /* TODO: Why do we need this - 1 clunkfest? */ + src += bufInPos; + pos += bufInPos; + if ((ret == 1) || (pos >= src_len) || (bufPos < 0x1800)) + break; + } + + return 0; +} + +/*************************************************************************** +* Function : MakeKey +* Description: This routine creates a simple key from a prefix code and +* an appended character. The key may be used to establish +* an order when building/searching a dictionary tree. +* Parameters : prefixCode - code for all but the last character of a +* string. +* suffixChar - the last character of a string +* Effects : None +* Returned : Key built from string represented as a prefix + char. Key +* format is {ms nibble of c} + prefix + {ls nibble of c} +***************************************************************************/ +static unsigned int +MakeKey(const unsigned int prefixCode, const unsigned char suffixChar) +{ + unsigned int key; + + /* position ms nibble */ + key = suffixChar & 0xF0; + key <<= MAX_CODE_LEN; + + /* include prefix code */ + key |= (prefixCode << 4); + + /* inclulde ls nibble */ + key |= (suffixChar & 0x0F); + + return key; +} + +/*************************************************************************** +* Function : MakeNode +* Description: This routine creates and initializes a dictionary entry +* for a string and the code word that encodes it. +* Parameters : codeWord - code word used to encode the string prefixCode + +* suffixChar +* prefixCode - code for all but the last character of a +* string. +* suffixChar - the last character of a string +* Effects : Node is allocated for new dictionary entry +* Returned : Pointer to newly allocated node or NULL on error. +* errno will be set on an error. +***************************************************************************/ +static dict_node_t * +MakeNode(const unsigned int codeWord, const unsigned int prefixCode, const unsigned char suffixChar) +{ + dict_node_t *node; + + node = malloc(sizeof(dict_node_t)); + + if (node != NULL) { + node->codeWord = codeWord; + node->prefixCode = prefixCode; + node->suffixChar = suffixChar; + + node->left = NULL; + node->right = NULL; + } + + return node; +} + +/*************************************************************************** +* Function : FreeTree +* Description: This routine will free all nodes of a tree rooted at the +* node past as a parameter. +* Parameters : node - root of tree to free +* Effects : frees allocated tree node from initial parameter down. +* Returned : none +***************************************************************************/ +static void +FreeTree(dict_node_t *node) +{ + if (node == NULL) + /* nothing to free */ + return; + + /* free left branch */ + if (node->left != NULL) + FreeTree(node->left); + + /* free right branch */ + if (node->right != NULL) + FreeTree(node->right); + + /* free root */ + free(node); +} + +/*************************************************************************** +* Function : FindDictionaryEntry +* Description: This routine searches the dictionary tree for an entry +* with a matching string (prefix code + suffix character). +* If one isn't found, the parent node for that string is +* returned. +* Parameters : prefixCode - code for the prefix of string +* c - last character in string +* Effects : None +* Returned : If string is in dictionary, pointer to node containing +* string, otherwise pointer to suitable parent node. NULL +* is returned for an empty tree. +***************************************************************************/ +static dict_node_t * +FindDictionaryEntry(dict_node_t *root, const int unsigned prefixCode, const unsigned char c) +{ + unsigned int searchKey, key; + + if (root == NULL) + return NULL; + + searchKey = MakeKey(prefixCode, c); /* key of string to find */ + + while (1) { + /* key of current node */ + key = MakeKey(root->prefixCode, root->suffixChar); + + if (key == searchKey) + /* current node contains string */ + return root; + else if (searchKey < key) { + if (root->left != NULL) + /* check left branch for string */ + root = root->left; + else + /* string isn't in tree, it can be added as a left child */ + return root; + } else { + if (root->right != NULL) + /* check right branch for string */ + root = root->right; + else + /* string isn't in tree, it can be added as a right child */ + return root; + } + } +} + +/*************************************************************************** +* Function : PutCodeWord +* Description: This function writes a code word from to an encoded file. +* In order to deal with endian issue the code word is +* written least significant byte followed by the remaining +* bits. +* Parameters : bfpOut - bit file containing the encoded data +* code - code word to add to the encoded data +* codeLen - length of the code word +* Effects : code word is written to the encoded output +* Returned : EOF for failure, ENOTSUP unsupported architecture, +* otherwise the number of bits written. If an error occurs +* after a partial write, the partially written bits will not +* be unwritten. +***************************************************************************/ +static int +PutCodeWord(char *dest, int code) +{ + static unsigned int realPos; + int ret = 0; + + if (bufPos >= 0x3000) + ret = -1; + else { + realPos = bufPos >> 1; + + if (bufPos & 1) { + /* Odd position. */ + dest[realPos] = (dest[realPos] & 0x0f) | ((code << 4) & 0xf0); + dest[realPos + 1] = (code >> 4) & 0xff; + } else { + /* Even position. */ + dest[realPos] = code & 0xff; + dest[realPos + 1] = ((code >> 8) & 0x0f); + } + + bufPos += 3; + + if (bufPos >= 0x3000) + ret = 1; + } + + return ret; +} diff --git a/src/floppy/lzw/lzwlocal.h b/src/floppy/lzw/lzwlocal.h new file mode 100644 index 0000000000..79d1f9646b --- /dev/null +++ b/src/floppy/lzw/lzwlocal.h @@ -0,0 +1,63 @@ +/*************************************************************************** +* Header for Lempel-Ziv-Welch Encoding and Decoding Library +* +* File : lzwlocal.h +* Purpose : Provides constant definitions for functions values used within +* the functions for Lempel-Ziv-Welch encoding/decoding. +* Author : Michael Dipperstein +* Date : February 22, 2015 +* +**************************************************************************** +* +* LZW: An ANSI C Lempel-Ziv-Welch Encoding/Decoding Routines +* Copyright (C) 2015 by +* Michael Dipperstein (mdipperstein@gmail.com) +* +* This file is part of the lzw library. +* +* The lzw library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public License as +* published by the Free Software Foundation; either version 3 of the +* License, or (at your option) any later version. +* +* The lzw library is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +* General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this program. If not, see . +* +***************************************************************************/ + +#ifndef _LZWLOCAL_H_ +#define _LZWLOCAL_H_ +/*************************************************************************** +* INCLUDED FILES +***************************************************************************/ +#include +#include + +/*************************************************************************** +* CONSTANTS +***************************************************************************/ +#define MIN_CODE_LEN 12 /* min # bits in a code word */ +#define MAX_CODE_LEN 12 /* max # bits in a code word */ + +#define FIRST_CODE (1 << CHAR_BIT) /* value of 1st string code */ +#define MAX_CODES (1 << MAX_CODE_LEN) + +#if (MIN_CODE_LEN <= CHAR_BIT) +#error Code words must be larger than 1 character +#endif + +#if ((MAX_CODES - 1) > INT_MAX) +#error There cannot be more codes than can fit in an integer +#endif + +/*************************************************************************** +* MACROS +***************************************************************************/ +#define CURRENT_MAX_CODES(bits) ((unsigned int)(1 << (bits))) + +#endif /* ndef _LZWLOCAL_H_ */ diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index 83dcd4836a..6b44a22366 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -9,9 +9,16 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(game OBJECT gameport.c joystick_standard.c - joystick_ch_flightstick_pro.c joystick_sw_pad.c joystick_tm_fcs.c) +add_library(game OBJECT + gameport.c + joystick_standard.c + joystick_ch_flightstick_pro.c + joystick_sw_pad.c + joystick_tm_fcs.c +) diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 7962c38e3e..cab008d0a7 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -92,9 +92,7 @@ sw_timer_over(void *priv) if (sw->poll_left == 1 && !sw->poll_clock) timer_advance_u64(&sw->poll_timer, TIMER_USEC * 160); else if (sw->poll_left) - timer_advance_u64(&sw->poll_timer, TIMER_USEC * 5); - else - timer_disable(&sw->poll_timer); + timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 5); } static void @@ -173,11 +171,9 @@ sw_write(void *priv) if (!JOYSTICK_PRESENT(0)) return; - timer_process(); - if (!sw->poll_left) { sw->poll_clock = 1; - timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 50); + timer_set_delay_u64(&sw->poll_timer, TIMER_USEC * 40); if (time_since_last > 9900 && time_since_last < 9940) { sw->poll_mode = 0; diff --git a/src/gdbstub.c b/src/gdbstub.c index 7036374220..42e1fc46de 100644 --- a/src/gdbstub.c +++ b/src/gdbstub.c @@ -40,6 +40,7 @@ #include <86box/86box.h> #include "cpu.h" #include "x86seg.h" +#include "x87_sf.h" #include "x87.h" #include "x87_ops_conv.h" #include <86box/io.h> @@ -365,13 +366,7 @@ gdbstub_break(void) static void gdbstub_jump(uint32_t new_pc) { - /* Nasty hack; qemu always uses the full 32-bit EIP internally... */ - if (cpu_state.op32 || ((new_pc >= cs) && (new_pc < (cs + 65536)))) { - cpu_state.pc = new_pc - cs; - } else { - loadseg((new_pc >> 4) & 0xf000, &cpu_state.seg_cs); - cpu_state.pc = new_pc & 0xffff; - } + cpu_state.pc = new_pc - cs; flushmmucache(); } @@ -1518,6 +1513,7 @@ gdbstub_client_thread(void *priv) case '$': /* packet start */ /* Wait for any existing packets to be processed. */ thread_wait_event(client->processed_event, -1); + thread_set_event(client->processed_event); client->packet_pos = 0; break; @@ -1535,6 +1531,7 @@ gdbstub_client_thread(void *priv) case 0x03: /* break */ /* Wait for any existing packets to be processed. */ thread_wait_event(client->processed_event, -1); + thread_set_event(client->processed_event); /* Break immediately. */ gdbstub_log("GDB Stub: Break requested\n"); @@ -1544,6 +1541,7 @@ gdbstub_client_thread(void *priv) default: /* Wait for any existing packets to be processed, just in case. */ thread_wait_event(client->processed_event, -1); + thread_set_event(client->processed_event); if (client->packet_pos < (sizeof(client->packet) - 1)) { /* Append byte to the packet. */ diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index f76d70797c..7d5709d30f 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -21,7 +21,8 @@ #define EMU_86BOX_H /* Configuration values. */ -#define SERIAL_MAX 4 +#define GFXCARD_MAX 2 +#define SERIAL_MAX 7 #define PARALLEL_MAX 4 #define SCREEN_RES_X 640 #define SCREEN_RES_Y 480 @@ -124,7 +125,7 @@ extern int force_43; /* (C) video */ extern int video_filter_method; /* (C) video */ extern int video_vsync; /* (C) video */ extern int video_framerate; /* (C) video */ -extern int gfxcard[2]; /* (C) graphics/video card */ +extern int gfxcard[GFXCARD_MAX]; /* (C) graphics/video card */ extern char video_shader[512]; /* (C) video */ extern int bugger_enabled; /* (C) enable ISAbugger */ extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */ @@ -152,6 +153,7 @@ extern int enable_discord; /* (C) enable Discord integration */ extern int other_ide_present; /* IDE controllers from non-IDE cards are present */ extern int other_scsi_present; /* SCSI controllers from non-SCSI cards are present */ +extern int hard_reset_pending; extern int fixed_size_x; extern int fixed_size_y; extern int do_auto_pause; /* (C) Auto-pause the emulator on focus loss */ diff --git a/src/include/86box/cartridge.h b/src/include/86box/cartridge.h index 2fa0a9358c..2ea7ec7347 100644 --- a/src/include/86box/cartridge.h +++ b/src/include/86box/cartridge.h @@ -21,7 +21,10 @@ extern "C" { #endif +#define CART_IMAGE_HISTORY 4 + extern char cart_fns[2][512]; +extern char *cart_image_history[2][CART_IMAGE_HISTORY]; extern void cart_load(int drive, char *fn); extern void cart_close(int drive); diff --git a/src/include/86box/cassette.h b/src/include/86box/cassette.h index 3706ca632c..bb0899e248 100644 --- a/src/include/86box/cassette.h +++ b/src/include/86box/cassette.h @@ -153,10 +153,13 @@ void pc_cas_print_state(const pc_cassette_t *cas); void pc_cas_clock(pc_cassette_t *cas, unsigned long cnt); void pc_cas_advance(pc_cassette_t *cas); +#define CASSETTE_IMAGE_HISTORY 4 + extern pc_cassette_t *cassette; extern char cassette_fname[512]; extern char cassette_mode[512]; +extern char * cassette_image_history[CASSETTE_IMAGE_HISTORY]; extern unsigned long cassette_pos; extern unsigned long cassette_srate; extern int cassette_enable; diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index b3f5a5ea5b..636c151ce5 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -25,6 +25,7 @@ #define CD_STATUS_PLAYING_COMPLETED 5 /* Medium changed flag. */ +#define CD_STATUS_TRANSITION 0x40 #define CD_STATUS_MEDIUM_CHANGED 0x80 #define CD_TRACK_AUDIO 0x08 @@ -226,7 +227,6 @@ typedef struct cdrom { uint8_t speed; uint8_t cur_speed; - int is_dir; void *priv; char image_path[1024]; @@ -299,6 +299,7 @@ extern void cdrom_seek(cdrom_t *dev, uint32_t pos, uint8_t vendor_type); extern void cdrom_close_handler(uint8_t id); extern void cdrom_insert(uint8_t id); +extern void cdrom_exit(uint8_t id); extern void cdrom_eject(uint8_t id); extern void cdrom_reload(uint8_t id); diff --git a/src/include/86box/cdrom_image_backend.h b/src/include/86box/cdrom_image_backend.h index 5222e8aa04..cf4fe95c3e 100644 --- a/src/include/86box/cdrom_image_backend.h +++ b/src/include/86box/cdrom_image_backend.h @@ -53,6 +53,8 @@ typedef struct track_file_t { char fn[260]; FILE *fp; void *priv; + + int motorola; } track_file_t; typedef struct track_t { @@ -63,7 +65,7 @@ typedef struct track_t { int mode2; int form; int pre; - int pad; + int noskip; /* Do not skip by 8 bytes.*/ uint64_t start; uint64_t length; uint64_t skip; diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index d5a96baf94..e47bb489f5 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -24,6 +24,7 @@ extern const device_t acc2168_device; extern const device_t ali1217_device; extern const device_t ali1429_device; extern const device_t ali1429g_device; +extern const device_t ali1409_device; extern const device_t ali1435_device; extern const device_t ali1489_device; extern const device_t ali1531_device; @@ -38,6 +39,7 @@ extern const device_t amd640_device; /* Compaq */ extern const device_t compaq_386_device; +extern const device_t compaq_genoa_device; /* Contaq/Cypress */ extern const device_t contaq_82c596a_device; @@ -109,8 +111,12 @@ extern const device_t ioapic_device; /* OPTi */ extern const device_t opti283_device; extern const device_t opti291_device; +extern const device_t opti381_device; +extern const device_t opti391_device; +extern const device_t opti481_device; extern const device_t opti493_device; extern const device_t opti495_device; +extern const device_t opti499_device; extern const device_t opti601_device; extern const device_t opti602_device; extern const device_t opti802g_device; @@ -189,7 +195,7 @@ extern const device_t nec_mate_unk_device; extern const device_t phoenix_486_jumper_device; extern const device_t phoenix_486_jumper_pci_device; -#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) +#ifdef USE_OLIVETTI extern const device_t olivetti_eva_device; -#endif +#endif /* USE_OLIVETTI */ #endif /*EMU_CHIPSET_H*/ diff --git a/src/include/86box/config.h b/src/include/86box/config.h index 80c987162e..a043fb22a2 100644 --- a/src/include/86box/config.h +++ b/src/include/86box/config.h @@ -113,7 +113,8 @@ typedef struct config_t { # endif /* Other peripherals category */ - int fdc_type; /* Floppy disk controller type */ + int fdc_current[FDC_MAX]; /* Floppy disk controller type */ + int hdc_current[HDC_MAX]; /* Hard disk controller type */ int hdc; /* Hard disk controller */ int scsi_card; /* SCSI controller */ int ide_ter_enabled; /* Tertiary IDE controller enabled */ diff --git a/src/include/86box/device.h b/src/include/86box/device.h index 30ce1c093f..67a30b1c86 100644 --- a/src/include/86box/device.h +++ b/src/include/86box/device.h @@ -101,6 +101,7 @@ enum { DEVICE_COM = 0x100000, /* requires a serial port */ DEVICE_LPT = 0x200000, /* requires a parallel port */ DEVICE_KBC = 0x400000, /* is a keyboard controller */ + DEVICE_SOFTRESET = 0x800000, /* requires to be reset on soft reset */ DEVICE_ONBOARD = 0x40000000, /* is on-board */ DEVICE_PIT = 0x80000000, /* device is a PIT */ @@ -244,6 +245,9 @@ extern const char *device_get_internal_name(const device_t *dev); extern int machine_get_config_int(char *s); extern char *machine_get_config_string(char *s); +extern const device_t device_none; +extern const device_t device_internal; + #ifdef __cplusplus } #endif diff --git a/src/include/86box/fdc.h b/src/include/86box/fdc.h index 9529fde5c7..ef78239cd0 100644 --- a/src/include/86box/fdc.h +++ b/src/include/86box/fdc.h @@ -22,8 +22,6 @@ #ifndef EMU_FDC_H #define EMU_FDC_H -extern int fdc_type; - #define FDC_PRIMARY_ADDR 0x03f0 #define FDC_PRIMARY_IRQ 6 #define FDC_PRIMARY_DMA 2 @@ -40,23 +38,23 @@ extern int fdc_type; #define FDC_QUATERNARY_IRQ 6 #define FDC_QUATERNARY_DMA 2 -#define FDC_FLAG_PCJR 0x01 /* PCjr */ -#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ -#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ -#define FDC_FLAG_PS1 0x08 /* PS/1, PS/2 ISA */ -#define FDC_FLAG_SUPERIO 0x10 /* Super I/O chips */ -#define FDC_FLAG_START_RWC_1 0x20 /* W83877F, W83977F */ -#define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ -#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ -#define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */ -#define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */ -#define FDC_FLAG_UMC 0x400 /* UMC UM8398 */ -#define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ -#define FDC_FLAG_SEC 0x1000 /* Is Secondary */ -#define FDC_FLAG_TER 0x2000 /* Is Tertiary */ -#define FDC_FLAG_QUA 0x3000 /* Is Quaternary */ -#define FDC_FLAG_CHANNEL 0x3000 /* Channel mask */ -#define FDC_FLAG_NO_DSR_RESET 0x4000 /* Has no DSR reset */ +#define FDC_FLAG_PCJR 0x01 /* PCjr */ +#define FDC_FLAG_DISKCHG_ACTLOW 0x02 /* Amstrad, PS/1, PS/2 ISA */ +#define FDC_FLAG_AT 0x04 /* AT+, PS/x */ +#define FDC_FLAG_PS1 0x08 /* PS/1, PS/2 ISA */ +#define FDC_FLAG_SUPERIO 0x10 /* Super I/O chips */ +#define FDC_FLAG_START_RWC_1 0x20 /* W83877F, W83977F */ +#define FDC_FLAG_MORE_TRACKS 0x40 /* W83877F, W83977F, PC87306, PC87309 */ +#define FDC_FLAG_NSC 0x80 /* PC87306, PC87309 */ +#define FDC_FLAG_TOSHIBA 0x100 /* T1000, T1200 */ +#define FDC_FLAG_AMSTRAD 0x200 /* Non-AT Amstrad machines */ +#define FDC_FLAG_UMC 0x400 /* UMC UM8398 */ +#define FDC_FLAG_ALI 0x800 /* ALi M512x / M1543C */ +#define FDC_FLAG_NO_DSR_RESET 0x1000 /* Has no DSR reset */ +#define FDC_FLAG_NEC 0x2000 /* Is NEC upd765-compatible */ +#define FDC_FLAG_SEC 0x10000 /* Is Secondary */ +#define FDC_FLAG_TER 0x20000 /* Is Tertiary */ +#define FDC_FLAG_QUA 0x40000 /* Is Quaternary */ typedef struct fdc_t { uint8_t dor; @@ -122,7 +120,7 @@ typedef struct fdc_t { uint8_t params[15]; uint8_t specify[2]; uint8_t res[11]; - uint8_t eot[4]; + uint16_t eot[4]; uint8_t rwc[4]; uint16_t pcn[4]; diff --git a/src/include/86box/fdc_ext.h b/src/include/86box/fdc_ext.h index 0d821ac119..4b33ed7a15 100644 --- a/src/include/86box/fdc_ext.h +++ b/src/include/86box/fdc_ext.h @@ -22,10 +22,13 @@ #ifndef EMU_FDC_EXT_H #define EMU_FDC_EXT_H -extern int fdc_type; +#define FDC_MAX 2 + +extern int fdc_current[FDC_MAX]; /* Controller types. */ -#define FDC_INTERNAL 0 +#define FDC_NONE 0 +#define FDC_INTERNAL 1 extern const device_t fdc_b215_device; extern const device_t fdc_pii151b_device; @@ -41,4 +44,4 @@ extern const device_t *fdc_card_getdevice(int card); extern int fdc_card_has_config(int card); extern int fdc_card_available(int card); -#endif /*EMU_FDC_H*/ +#endif /*EMU_FDC_EXT_H*/ diff --git a/src/include/86box/fifo8.h b/src/include/86box/fifo8.h index 9f88ec408f..7dec1d57d2 100644 --- a/src/include/86box/fifo8.h +++ b/src/include/86box/fifo8.h @@ -69,28 +69,80 @@ extern uint8_t fifo8_pop(Fifo8 *fifo); /** * fifo8_pop_buf: * @fifo: FIFO to pop from + * @dest: the buffer to write the data into (can be NULL) + * @destlen: size of @dest and maximum number of bytes to pop + * + * Pop a number of elements from the FIFO up to a maximum of @destlen. + * The popped data is copied into the @dest buffer. + * Care is taken when the data wraps around in the ring buffer. + * + * Returns: number of bytes popped. + */ +extern uint32_t fifo8_pop_buf(Fifo8 *fifo, uint8_t *dest, uint32_t destlen); + +/** + * fifo8_pop_bufptr: + * @fifo: FIFO to pop from * @max: maximum number of bytes to pop - * @num: actual number of returned bytes + * @numptr: pointer filled with number of bytes returned (can be NULL) * - * Pop a number of elements from the FIFO up to a maximum of max. The buffer + * New code should prefer to use fifo8_pop_buf() instead of fifo8_pop_bufptr(). + * + * Pop a number of elements from the FIFO up to a maximum of @max. The buffer * containing the popped data is returned. This buffer points directly into - * the FIFO backing store and data is invalidated once any of the fifo8_* APIs - * are called on the FIFO. + * the internal FIFO backing store and data (without checking for overflow!) + * and is invalidated once any of the fifo8_* APIs are called on the FIFO. * * The function may return fewer bytes than requested when the data wraps * around in the ring buffer; in this case only a contiguous part of the data * is returned. * - * The number of valid bytes returned is populated in *num; will always return - * at least 1 byte. max must not be 0 or greater than the number of bytes in - * the FIFO. + * The number of valid bytes returned is populated in *@numptr; will always + * return at least 1 byte. max must not be 0 or greater than the number of + * bytes in the FIFO. * * Clients are responsible for checking the availability of requested data * using fifo8_num_used(). * * Returns: A pointer to popped data. */ -extern const uint8_t *fifo8_pop_buf(Fifo8 *fifo, uint32_t max, uint32_t *num); +extern const uint8_t *fifo8_pop_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr); + +/** + * fifo8_peek_bufptr: read upto max bytes from the fifo + * @fifo: FIFO to read from + * @max: maximum number of bytes to peek + * @numptr: pointer filled with number of bytes returned (can be NULL) + * + * Peek into a number of elements from the FIFO up to a maximum of @max. + * The buffer containing the data peeked into is returned. This buffer points + * directly into the FIFO backing store. Since data is invalidated once any + * of the fifo8_* APIs are called on the FIFO, it is the caller responsibility + * to access it before doing further API calls. + * + * The function may return fewer bytes than requested when the data wraps + * around in the ring buffer; in this case only a contiguous part of the data + * is returned. + * + * The number of valid bytes returned is populated in *@numptr; will always + * return at least 1 byte. max must not be 0 or greater than the number of + * bytes in the FIFO. + * + * Clients are responsible for checking the availability of requested data + * using fifo8_num_used(). + * + * Returns: A pointer to peekable data. + */ +extern const uint8_t *fifo8_peek_bufptr(Fifo8 *fifo, uint32_t max, uint32_t *numptr); + +/** + * fifo8_drop: + * @fifo: FIFO to drop bytes + * @len: number of bytes to drop + * + * Drop (consume) bytes from a FIFO. + */ +extern void fifo8_drop(Fifo8 *fifo, uint32_t len); /** * fifo8_reset: diff --git a/src/include/86box/hdc.h b/src/include/86box/hdc.h index 38c0a6e9a4..48235bb1e5 100644 --- a/src/include/86box/hdc.h +++ b/src/include/86box/hdc.h @@ -32,7 +32,9 @@ #define HDC_NONE 0 #define HDC_INTERNAL 1 -extern int hdc_current; +#define HDC_MAX 2 + +extern int hdc_current[HDC_MAX]; extern const device_t st506_xt_xebec_device; /* st506_xt_xebec */ extern const device_t st506_xt_wdxt_gen_device; /* st506_xt_wdxt_gen */ diff --git a/src/include/86box/isamem.h b/src/include/86box/isamem.h index 9a1841c53c..51fe50e330 100644 --- a/src/include/86box/isamem.h +++ b/src/include/86box/isamem.h @@ -64,6 +64,7 @@ extern const char *isamem_get_name(int t); extern const char *isamem_get_internal_name(int t); extern int isamem_get_from_internal_name(const char *s); extern const device_t *isamem_get_device(int t); +extern int isamem_has_config(int board); #ifdef __cplusplus } diff --git a/src/include/86box/isartc.h b/src/include/86box/isartc.h index 92c58e3506..0224180b36 100644 --- a/src/include/86box/isartc.h +++ b/src/include/86box/isartc.h @@ -58,6 +58,7 @@ extern void isartc_reset(void); extern const char *isartc_get_internal_name(int t); extern int isartc_get_from_internal_name(char *s); extern const device_t *isartc_get_device(int t); +extern int isartc_has_config(int board); #ifdef __cplusplus } diff --git a/src/include/86box/keyboard.h b/src/include/86box/keyboard.h index 8461236277..f233637ff7 100644 --- a/src/include/86box/keyboard.h +++ b/src/include/86box/keyboard.h @@ -222,9 +222,9 @@ extern const device_t keyboard_xt86_device; extern const device_t keyboard_xt_compaq_device; extern const device_t keyboard_xt_t1x00_device; extern const device_t keyboard_tandy_device; -# if defined(DEV_BRANCH) && defined(USE_LASERXT) +# ifdef USE_LASERXT extern const device_t keyboard_xt_lxt3_device; -# endif /*defined(DEV_BRANCH) && defined(USE_LASERXT) */ +# endif /* USE_LASERXT */ extern const device_t keyboard_xt_olivetti_device; extern const device_t keyboard_xt_zenith_device; extern const device_t keyboard_xt_hyundai_device; @@ -272,12 +272,14 @@ extern uint8_t keyboard_get_shift(void); extern void keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl); extern void keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl); extern int keyboard_recv(uint16_t key); +extern int keyboard_recv_ui(uint16_t key); extern int keyboard_isfsenter(void); extern int keyboard_isfsenter_up(void); extern int keyboard_isfsexit(void); extern int keyboard_isfsexit_up(void); extern int keyboard_ismsexit(void); extern void keyboard_set_is_amstrad(int ams); +extern void kbc_at_set_ps2(void *priv, uint8_t ps2); extern void kbc_at_set_fast_reset(uint8_t new_fast_reset); extern void kbc_at_handler(int set, void *priv); diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index a5b9223583..953ee7585d 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -232,6 +232,9 @@ enum { MACHINE_CHIPSET_INTEL_440GX, MACHINE_CHIPSET_OPTI_283, MACHINE_CHIPSET_OPTI_291, + MACHINE_CHIPSET_OPTI_381, + MACHINE_CHIPSET_OPTI_391, + MACHINE_CHIPSET_OPTI_481, MACHINE_CHIPSET_OPTI_493, MACHINE_CHIPSET_OPTI_495, MACHINE_CHIPSET_OPTI_499, @@ -274,6 +277,7 @@ enum { MACHINE_CHIPSET_VLSI_VL82C481, MACHINE_CHIPSET_VLSI_VL82C486, MACHINE_CHIPSET_WD76C10, + MACHINE_CHIPSET_ZYMOS_POACH, MACHINE_CHIPSET_MAX }; @@ -432,9 +436,10 @@ extern int machine_at_ibmxt286_init(const machine_t *); extern int machine_at_siemens_init(const machine_t *); // Siemens PCD-2L. N82330 discrete machine. It segfaults in some places -#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) +extern int machine_at_wellamerastar_init(const machine_t *); // Wells American A*Star with custom award BIOS +#ifdef USE_OPEN_AT extern int machine_at_openat_init(const machine_t *); -#endif +#endif /* USE_OPEN_AT */ /* m_at_286_386sx.c */ extern int machine_at_tg286m_init(const machine_t *); @@ -463,9 +468,9 @@ extern int machine_at_deskmaster286_init(const machine_t *); extern int machine_at_pc8_init(const machine_t *); extern int machine_at_3302_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) +#ifdef USE_OLIVETTI extern int machine_at_m290_init(const machine_t *); -#endif +#endif /* USE_OLIVETTI */ extern int machine_at_shuttle386sx_init(const machine_t *); extern int machine_at_adi386sx_init(const machine_t *); @@ -481,12 +486,21 @@ extern int machine_at_325ax_init(const machine_t *); extern int machine_at_mr1217_init(const machine_t *); extern int machine_at_pja511m_init(const machine_t *); extern int machine_at_prox1332_init(const machine_t *); +extern int machine_at_acer100t_init(const machine_t *); extern int machine_at_awardsx_init(const machine_t *); extern int machine_at_pc916sx_init(const machine_t *); /* m_at_386dx_486.c */ +/* Note to jriwanek: When merging this into my branch, please make + sure this appear here (and in the .c file) in the order and position + in which they appear in the machine table. */ +extern int machine_at_dataexpert386wb_init(const machine_t *); +extern int machine_at_genoa486_init(const machine_t *); +extern int machine_at_ga486l_init(const machine_t *); +extern int machine_at_cougar_init(const machine_t *); + extern int machine_at_acc386_init(const machine_t *); extern int machine_at_asus386_init(const machine_t *); extern int machine_at_ecs386_init(const machine_t *); @@ -712,9 +726,9 @@ extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_ma23c_init(const machine_t *); extern int machine_at_nupro592_init(const machine_t *); extern int machine_at_tx97_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_AN430TX) +#ifdef USE_AN430TX extern int machine_at_an430tx_init(const machine_t *); -#endif +#endif /* USE_AN430TX */ extern int machine_at_ym430tx_init(const machine_t *); extern int machine_at_thunderbolt_init(const machine_t *); extern int machine_at_mb540n_init(const machine_t *); @@ -876,7 +890,7 @@ extern int machine_ps2_model_70_type4_init(const machine_t *); /* m_tandy.c */ extern int tandy1k_eeprom_read(void); -extern int machine_tandy_init(const machine_t *); +extern int machine_tandy1000sx_init(const machine_t *); extern int machine_tandy1000hx_init(const machine_t *); extern int machine_tandy1000sl2_init(const machine_t *); @@ -919,6 +933,7 @@ extern int machine_xt_v20xt_init(const machine_t *); extern int machine_xt_iskra3104_init(const machine_t *); extern int machine_xt_pravetz16_imko4_init(const machine_t *); +extern int machine_xt_pravetz16s_cpu12p_init(const machine_t *); extern int machine_xt_micoms_xl7turbo_init(const machine_t *); /* m_xt_compaq.c */ @@ -926,10 +941,10 @@ extern int machine_xt_compaq_deskpro_init(const machine_t *); extern int machine_xt_compaq_portable_init(const machine_t *); /* m_xt_laserxt.c */ -#if defined(DEV_BRANCH) && defined(USE_LASERXT) +#ifdef USE_LASERXT extern int machine_xt_laserxt_init(const machine_t *); extern int machine_xt_lxt3_init(const machine_t *); -#endif +#endif /* USE_LASERXT */ /* m_xt_philips.c */ extern int machine_xt_p3105_init(const machine_t *); diff --git a/src/include/86box/mem.h b/src/include/86box/mem.h index a130309c40..ad89e4b4f9 100644 --- a/src/include/86box/mem.h +++ b/src/include/86box/mem.h @@ -391,6 +391,11 @@ extern void mem_mapping_set_handler(mem_mapping_t *, void (*write_w)(uint32_t addr, uint16_t val, void *priv), void (*write_l)(uint32_t addr, uint32_t val, void *priv)); +extern void mem_mapping_set_write_handler(mem_mapping_t *, + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv)); + extern void mem_mapping_set_p(mem_mapping_t *, void *priv); extern void mem_mapping_set_addr(mem_mapping_t *, @@ -441,6 +446,7 @@ extern void mem_flush_write_page(uint32_t addr, uint32_t virt); extern void mem_reset_page_blocks(void); extern void flushmmucache(void); +extern void flushmmucache_pc(void); extern void flushmmucache_nopc(void); extern void mem_debug_check_addr(uint32_t addr, int write); @@ -451,6 +457,7 @@ extern void mem_a20_recalc(void); extern void mem_init(void); extern void mem_close(void); extern void mem_reset(void); +extern void mem_remap_top_ex(int kb, uint32_t start); extern void mem_remap_top(int kb); extern void umc_smram_recalc(uint32_t start, int set); diff --git a/src/include/86box/midi.h b/src/include/86box/midi.h index 7f7ad89ae5..3a41c2cb5e 100644 --- a/src/include/86box/midi.h +++ b/src/include/86box/midi.h @@ -32,6 +32,7 @@ typedef struct midi_device_t { void (*play_sysex)(uint8_t *sysex, unsigned int len); void (*play_msg)(uint8_t *msg); void (*poll)(void); + void (*reset)(void); int (*write)(uint8_t val); } midi_device_t; @@ -77,6 +78,7 @@ extern void midi_raw_out_thru_rt_byte(uint8_t val); extern void midi_raw_out_byte(uint8_t val); extern void midi_clear_buffer(void); extern void midi_poll(void); +extern void midi_reset(void); extern void midi_in_handler(int set, void (*msg)(void *priv, uint8_t *msg, uint32_t len), int (*sysex)(void *priv, uint8_t *buffer, uint32_t len, int abort), void *priv); extern void midi_in_handlers_clear(void); @@ -102,18 +104,18 @@ extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #ifdef EMU_DEVICE_H extern const device_t rtmidi_output_device; extern const device_t rtmidi_input_device; -# if defined(DEV_BRANCH) && defined(USE_OPL4ML) +# ifdef USE_OPL4ML extern const device_t opl4_midi_device; -# endif +# endif /* USE_OPL4ML */ # ifdef USE_FLUIDSYNTH extern const device_t fluidsynth_device; -# endif +# endif /* USE_FLUIDSYNTH */ # ifdef USE_MUNT extern const device_t mt32_old_device; extern const device_t mt32_new_device; extern const device_t cm32l_device; extern const device_t cm32ln_device; -# endif +# endif /* USE_MUNT */ #endif #endif /*EMU_SOUND_MIDI_H*/ diff --git a/src/include/86box/mouse.h b/src/include/86box/mouse.h index da14b86375..b7d3a87d59 100644 --- a/src/include/86box/mouse.h +++ b/src/include/86box/mouse.h @@ -50,7 +50,7 @@ extern "C" { #endif extern int mouse_type; -extern int mouse_input_mode; /* 1 = Absolute, 0 = Relative */ +extern int mouse_input_mode; /* 2 = Absolute (Visible Crosshair), 1 = Absolute, 0 = Relative */ extern int mouse_timed; /* 1 = Timed, 0 = Constant */ extern int mouse_tablet_in_proximity; extern double mouse_x_abs; @@ -71,9 +71,12 @@ extern const device_t mouse_mssystems_device; extern const device_t mouse_msserial_device; extern const device_t mouse_ltserial_device; extern const device_t mouse_ps2_device; +# ifdef USE_WACOM extern const device_t mouse_wacom_device; extern const device_t mouse_wacom_artpad_device; +# endif extern const device_t mouse_usb_mouse_device; +extern const device_t mouse_mtouch_device; #endif extern void mouse_clear_x(void); diff --git a/src/include/86box/net_dp8390.h b/src/include/86box/net_dp8390.h index e9e1e6c719..5533668088 100644 --- a/src/include/86box/net_dp8390.h +++ b/src/include/86box/net_dp8390.h @@ -171,6 +171,8 @@ typedef struct dp8390_t { /* DP8390 memory */ uint8_t *mem; /* on-chip packet memory */ + uint8_t sink_buffer[4096]; + uint8_t macaddr[32]; /* ASIC ROM'd MAC address, even bytes */ uint8_t macaddr_size, /* Defaults to 16 but can be 32 */ flags, /* Flags affecting some behaviors. */ diff --git a/src/include/86box/net_ne2000.h b/src/include/86box/net_ne2000.h index 75185cf906..cb17ef8b11 100644 --- a/src/include/86box/net_ne2000.h +++ b/src/include/86box/net_ne2000.h @@ -37,15 +37,17 @@ #define NET_NE2000_H enum { - NE2K_NONE = 0, - NE2K_NE1000 = 1, /* 8-bit ISA NE1000 */ - NE2K_NE1000_COMPAT = 2, /* 8-bit ISA NE1000-Compatible */ - NE2K_NE2000 = 3, /* 16-bit ISA NE2000 */ - NE2K_NE2000_COMPAT = 4, /* 16-bit ISA NE2000-Compatible */ - NE2K_ETHERNEXT_MC = 5, /* 16-bit MCA EtherNext/MC */ - NE2K_RTL8019AS = 6, /* 16-bit ISA PnP Realtek 8019AS */ - NE2K_DE220P = 7, /* 16-bit ISA PnP D-Link DE-220P */ - NE2K_RTL8029AS = 8 /* 32-bit PCI Realtek 8029AS */ + NE2K_NONE = 0, + NE2K_NE1000 = 1, /* 8-bit ISA NE1000 */ + NE2K_NE1000_COMPAT = 2, /* 8-bit ISA NE1000-Compatible */ + NE2K_NE2000 = 3, /* 16-bit ISA NE2000 */ + NE2K_NE2000_COMPAT = 4, /* 16-bit ISA NE2000-Compatible */ + NE2K_NE2000_COMPAT_8BIT = 5, /* 8-bit ISA NE2000-Compatible, like: https://github.com/skiselev/isa8_eth */ + NE2K_ETHERNEXT_MC = 6, /* 16-bit MCA EtherNext/MC */ + NE2K_RTL8019AS = 7, /* 16-bit ISA PnP Realtek 8019AS */ + NE2K_DE220P = 8, /* 16-bit ISA PnP D-Link DE-220P */ + NE2K_RTL8029AS = 9, /* 32-bit PCI Realtek 8029AS */ + /* Check nic_init() if adding items after this point. */ }; #endif /*NET_NE2000_H*/ diff --git a/src/include/86box/network.h b/src/include/86box/network.h index 9588de86a2..fa6408790d 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -211,6 +211,7 @@ extern const device_t ne1000_device; extern const device_t ne1000_compat_device; extern const device_t ne2000_device; extern const device_t ne2000_compat_device; +extern const device_t ne2000_compat_8bit_device; extern const device_t ethernext_mc_device; extern const device_t rtl8019as_device; extern const device_t de220p_device; diff --git a/src/include/86box/pit.h b/src/include/86box/pit.h index eb03fd2c9e..3c5a9cb522 100644 --- a/src/include/86box/pit.h +++ b/src/include/86box/pit.h @@ -19,6 +19,8 @@ #ifndef EMU_PIT_H #define EMU_PIT_H +#define NUM_COUNTERS 3 + typedef struct ctr_t { uint8_t m; uint8_t ctrl; @@ -68,7 +70,7 @@ typedef struct PIT { int clock; pc_timer_t callback_timer; - ctr_t counters[3]; + ctr_t counters[NUM_COUNTERS]; uint8_t ctrl; diff --git a/src/include/86box/pit_fast.h b/src/include/86box/pit_fast.h index 5650ffb4d2..f824bad688 100644 --- a/src/include/86box/pit_fast.h +++ b/src/include/86box/pit_fast.h @@ -68,7 +68,7 @@ typedef struct ctrf_t { typedef struct pitf_t { int flags; - ctrf_t counters[3]; + ctrf_t counters[NUM_COUNTERS]; uint8_t ctrl; diff --git a/src/include/86box/plat.h b/src/include/86box/plat.h index 975133f6c6..4a310ab44f 100644 --- a/src/include/86box/plat.h +++ b/src/include/86box/plat.h @@ -47,7 +47,9 @@ enum { STRING_HW_NOT_AVAILABLE_MACHINE, /* "Machine \"%hs\" is not available..." */ STRING_HW_NOT_AVAILABLE_VIDEO, /* "Video card \"%hs\" is not available..." */ STRING_HW_NOT_AVAILABLE_VIDEO2, /* "Video card #2 \"%hs\" is not available..." */ - STRING_MONITOR_SLEEP /* "Monitor in sleep mode" */ + STRING_MONITOR_SLEEP, /* "Monitor in sleep mode" */ + STRING_GHOSTPCL_ERROR_TITLE, /* "Unable to initialize GhostPCL" */ + STRING_GHOSTPCL_ERROR_DESC /* "gpcl6dll32.dll/gpcl6dll64.dll/libgpcl6 is required..." */ }; /* The Win32 API uses _wcsicmp. */ @@ -151,7 +153,7 @@ extern uint32_t plat_get_ticks(void); extern void plat_delay_ms(uint32_t count); extern void plat_pause(int p); extern void plat_mouse_capture(int on); -extern int plat_vidapi(char *name); +extern int plat_vidapi(const char *name); extern char *plat_vidapi_name(int api); extern void plat_resize(int x, int y, int monitor_index); extern void plat_resize_request(int x, int y, int monitor_index); diff --git a/src/include/86box/port_92.h b/src/include/86box/port_92.h index 2dd4319be6..838b7ca289 100644 --- a/src/include/86box/port_92.h +++ b/src/include/86box/port_92.h @@ -37,6 +37,7 @@ extern void port_92_add(void *priv); extern void port_92_remove(void *priv); extern const device_t port_92_device; +extern const device_t port_92_key_device; extern const device_t port_92_inv_device; extern const device_t port_92_word_device; extern const device_t port_92_pci_device; diff --git a/src/include/86box/prt_devs.h b/src/include/86box/prt_devs.h index 3d9d6673a4..1379c8fa83 100644 --- a/src/include/86box/prt_devs.h +++ b/src/include/86box/prt_devs.h @@ -4,5 +4,8 @@ extern const lpt_device_t lpt_prt_text_device; extern const lpt_device_t lpt_prt_escp_device; extern const lpt_device_t lpt_prt_ps_device; +#ifdef USE_PCL +extern const lpt_device_t lpt_prt_pcl_device; +#endif #endif /*EMU_PRT_DEVS_H*/ diff --git a/src/include/86box/scsi_ncr5380.h b/src/include/86box/scsi_ncr5380.h index 8baa4f9d8b..55692075bb 100644 --- a/src/include/86box/scsi_ncr5380.h +++ b/src/include/86box/scsi_ncr5380.h @@ -138,9 +138,6 @@ extern const device_t scsi_t128_device; extern const device_t scsi_t228_device; extern const device_t scsi_t130b_device; extern const device_t scsi_ls2000_device; -#if defined(DEV_BRANCH) && defined(USE_SUMO) -extern const device_t scsi_scsiat_device; -#endif #endif #endif /*SCSI_NCR5380_H*/ diff --git a/src/include/86box/scsi_pcscsi.h b/src/include/86box/scsi_pcscsi.h index 3acee78f9c..8547aba256 100644 --- a/src/include/86box/scsi_pcscsi.h +++ b/src/include/86box/scsi_pcscsi.h @@ -25,6 +25,7 @@ #ifndef SCSI_PCSCSI_H #define SCSI_PCSCSI_H +extern const device_t am53c974_pci_device; extern const device_t dc390_pci_device; extern const device_t ncr53c90a_mca_device; diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index 0f18743029..8d5964de57 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -476,7 +476,8 @@ typedef struct x54x_t { /* 8 bytes */ char *bios_path; /* path to BIOS image file */ char *mcode_path; /* path to microcode image file, needed by the AHA-1542CP */ - char *nvr_path; /* path to NVR image file */ + + char nvr_path[64]; /* path to NVR image file */ /* 56 bytes */ /* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */ diff --git a/src/include/86box/serial.h b/src/include/86box/serial.h index c2312f562d..a205c7cecb 100644 --- a/src/include/86box/serial.h +++ b/src/include/86box/serial.h @@ -43,6 +43,18 @@ #define COM3_IRQ 4 #define COM4_ADDR 0x02e8 #define COM4_IRQ 3 +// The following support being assingned IRQ 3, 4, 5, 9, 10, 11, 12 or 15 +// There doesn't appear to be any specific standard however +// So defaults have been chosen arbitarily +// TODO: Allow configuration of the IRQ in the UI +//#define COM5_ADDR 0x03f0 +//#define COM5_IRQ 3 +#define COM5_ADDR 0x02f0 +#define COM5_IRQ 11 +#define COM6_ADDR 0x03e0 +#define COM6_IRQ 10 +#define COM7_ADDR 0x02e0 +#define COM7_IRQ 9 struct serial_device_s; struct serial_s; diff --git a/src/include/86box/sio.h b/src/include/86box/sio.h index d5fc88fb46..2dbe97ab06 100644 --- a/src/include/86box/sio.h +++ b/src/include/86box/sio.h @@ -42,6 +42,7 @@ extern const device_t fdc37c931apm_device; extern const device_t fdc37c931apm_compaq_device; extern const device_t fdc37c932fr_device; extern const device_t fdc37c932qf_device; +extern const device_t fdc37c932_device; extern const device_t fdc37c935_device; extern const device_t fdc37c935_370_device; extern const device_t fdc37c935_no_nvr_device; @@ -74,9 +75,9 @@ extern const device_t prime3b_ide_device; extern const device_t prime3c_device; extern const device_t prime3c_ide_device; extern const device_t ps1_m2133_sio; -#if defined(DEV_BRANCH) && defined(USE_SIO_DETECT) +#ifdef USE_SIO_DETECT extern const device_t sio_detect_device; -#endif +#endif /* USE_SIO_DETECT */ extern const device_t um8663af_device; extern const device_t um8663af_ide_device; extern const device_t um8663af_sec_device; @@ -87,6 +88,7 @@ extern const device_t um8669f_device; extern const device_t um8669f_ide_device; extern const device_t um8669f_ide_sec_device; extern const device_t via_vt82c686_sio_device; +extern const device_t vl82c113_device; extern const device_t w83787f_88h_device; extern const device_t w83787f_device; extern const device_t w83787f_ide_device; diff --git a/src/include/86box/snd_mpu401.h b/src/include/86box/snd_mpu401.h index 8cd275af88..6dd99379e0 100644 --- a/src/include/86box/snd_mpu401.h +++ b/src/include/86box/snd_mpu401.h @@ -26,9 +26,9 @@ #define MPU401_VERSION 0x15 #define MPU401_REVISION 0x01 -#define MPU401_QUEUE 1024 +#define MPU401_QUEUE 32 #define MPU401_INPUT_QUEUE 1024 -#define MPU401_TIMECONSTANT (60000000 / 1000.0f) +#define MPU401_TIMECONSTANT (60000000.0 / 1000.0) #define MPU401_RESETBUSY 27.0f /*helpers*/ @@ -89,7 +89,7 @@ typedef struct mpu_t { uint32_t ch_toref[16]; struct track { int counter; - uint8_t value[3]; + uint8_t value[8]; uint8_t sys_val; uint8_t vlength; uint8_t length; @@ -106,7 +106,6 @@ typedef struct mpu_t { int wsm; int wsd_start; int run_irq; - int irq_pending; int track_req; int send_now; int eoi_scheduled; @@ -116,9 +115,11 @@ typedef struct mpu_t { int sysex_in_finished; int rec_copy; RecState rec; + uint8_t irq_pending; uint8_t tmask; uint8_t cmask; uint8_t amask; + uint8_t queued_eois; uint8_t last_rtcmd; uint16_t midi_mask; uint16_t req_mask; diff --git a/src/include/86box/snd_opl_nuked.h b/src/include/86box/snd_opl_nuked.h index e53f860f12..0b203fe312 100644 --- a/src/include/86box/snd_opl_nuked.h +++ b/src/include/86box/snd_opl_nuked.h @@ -20,4 +20,181 @@ #ifndef SOUND_OPL_NUKED_H #define SOUND_OPL_NUKED_H +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifndef OPL_ENABLE_STEREOEXT +#define OPL_ENABLE_STEREOEXT 0 +#endif + +#define OPL_WRITEBUF_SIZE 1024 +#define OPL_WRITEBUF_DELAY 2 + +typedef struct _opl3_slot opl3_slot; +typedef struct _opl3_channel opl3_channel; +typedef struct _opl3_chip opl3_chip; + +struct _opl3_slot { + opl3_channel *channel; + opl3_chip *chip; + int16_t out; + int16_t fbmod; + int16_t *mod; + int16_t prout; + uint16_t eg_rout; + uint16_t eg_out; + uint8_t eg_inc; + uint8_t eg_gen; + uint8_t eg_rate; + uint8_t eg_ksl; + uint8_t *trem; + uint8_t reg_vib; + uint8_t reg_type; + uint8_t reg_ksr; + uint8_t reg_mult; + uint8_t reg_ksl; + uint8_t reg_tl; + uint8_t reg_ar; + uint8_t reg_dr; + uint8_t reg_sl; + uint8_t reg_rr; + uint8_t reg_wf; + uint8_t key; + uint32_t pg_reset; + uint32_t pg_phase; + uint16_t pg_phase_out; + uint8_t slot_num; +}; + +struct _opl3_channel { + opl3_slot *slotz[2]; // Don't use "slots" keyword to avoid conflict with Qt applications + opl3_channel *pair; + opl3_chip *chip; + int16_t *out[4]; + +#if OPL_ENABLE_STEREOEXT + int32_t leftpan; + int32_t rightpan; +#endif + + uint8_t chtype; + uint16_t f_num; + uint8_t block; + uint8_t fb; + uint8_t con; + uint8_t alg; + uint8_t ksv; + uint16_t cha; + uint16_t chb; + uint16_t chc; + uint16_t chd; + uint8_t ch_num; +}; + +typedef struct _opl3_writebuf { + uint64_t time; + uint16_t reg; + uint8_t data; +} opl3_writebuf; + +struct _opl3_chip { + opl3_channel channel[18]; + opl3_slot slot[36]; + uint16_t timer; + uint64_t eg_timer; + uint8_t eg_timerrem; + uint8_t eg_state; + uint8_t eg_add; + uint8_t eg_timer_lo; + uint8_t newm; + uint8_t nts; + uint8_t rhy; + uint8_t vibpos; + uint8_t vibshift; + uint8_t tremolo; + uint8_t tremolopos; + uint8_t tremoloshift; + uint32_t noise; + int16_t zeromod; + int32_t mixbuff[4]; + uint8_t rm_hh_bit2; + uint8_t rm_hh_bit3; + uint8_t rm_hh_bit7; + uint8_t rm_hh_bit8; + uint8_t rm_tc_bit3; + uint8_t rm_tc_bit5; + +#if OPL_ENABLE_STEREOEXT + uint8_t stereoext; +#endif + + // OPL3L + int32_t rateratio; + int32_t samplecnt; + int32_t oldsamples[4]; + int32_t samples[4]; + + uint64_t writebuf_samplecnt; + uint32_t writebuf_cur; + uint32_t writebuf_last; + uint64_t writebuf_lasttime; + opl3_writebuf writebuf[OPL_WRITEBUF_SIZE]; +}; + +typedef struct { + opl3_chip opl; + int8_t flags; + int8_t pad; + + uint16_t port; + uint8_t status; + uint8_t timer_ctrl; + uint16_t timer_count[2]; + uint16_t timer_cur_count[2]; + + pc_timer_t timers[2]; + + int pos; + int32_t buffer[MUSICBUFLEN * 2]; +} nuked_drv_t; + +enum { + FLAG_CYCLES = 0x02, + FLAG_OPL3 = 0x01 +}; + +enum { + STAT_TMR_OVER = 0x60, + STAT_TMR1_OVER = 0x40, + STAT_TMR2_OVER = 0x20, + STAT_TMR_ANY = 0x80 +}; + +enum { + CTRL_RESET = 0x80, + CTRL_TMR_MASK = 0x60, + CTRL_TMR1_MASK = 0x40, + CTRL_TMR2_MASK = 0x20, + CTRL_TMR2_START = 0x02, + CTRL_TMR1_START = 0x01 +}; + +void OPL3_Generate(opl3_chip *chip, int32_t *buf); +void OPL3_GenerateResampled(opl3_chip *chip, int32_t *buf); +void OPL3_Reset(opl3_chip *chip, uint32_t samplerate); +void OPL3_WriteReg(void *priv, uint16_t reg, uint8_t val); +void OPL3_WriteRegBuffered(void *priv, uint16_t reg, uint8_t val); +void OPL3_GenerateStream(opl3_chip *chip, int32_t *sndptr, uint32_t numsamples); + +static void OPL3_Generate4Ch(void *priv, int32_t *buf4); +void OPL3_Generate4Ch_Resampled(opl3_chip *chip, int32_t *buf4); +void OPL3_Generate4Ch_Stream(opl3_chip *chip, int32_t *sndptr1, int32_t *sndptr2, uint32_t numsamples); + +#ifdef __cplusplus +} +#endif + #endif /*SOUND_OPL_NUKED_H*/ diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index b26c5f06ec..70fcff3879 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -187,6 +187,8 @@ typedef struct sb_t { uint8_t pnp_rom[512]; uint16_t opl_pnp_addr; + + uint16_t midi_addr; uint16_t gameport_addr; void *opl_mixer; diff --git a/src/include/86box/snd_sb_dsp.h b/src/include/86box/snd_sb_dsp.h index c179fd1979..0bc719d98f 100644 --- a/src/include/86box/snd_sb_dsp.h +++ b/src/include/86box/snd_sb_dsp.h @@ -91,6 +91,8 @@ typedef struct sb_dsp_t { uint8_t sbref; int8_t sbstep; + uint8_t activity; + int sbdacpos; int sbleftright; @@ -141,6 +143,7 @@ typedef struct sb_dsp_t { int wb_full; pc_timer_t irq_timer; + pc_timer_t irq16_timer; int busy_count; diff --git a/src/include/86box/snd_sn76489.h b/src/include/86box/snd_sn76489.h index 6e7399d548..81d9ad2293 100644 --- a/src/include/86box/snd_sn76489.h +++ b/src/include/86box/snd_sn76489.h @@ -20,6 +20,9 @@ typedef struct sn76489_t { int freqhi[4]; int vol[4]; uint32_t shift; + uint32_t white_noise_tap_1; + uint32_t white_noise_tap_2; + uint32_t feedback_mask; uint8_t noise; int lasttone; uint8_t firstdat; diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 9896b54223..9895e73d76 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -179,6 +179,10 @@ extern const device_t ess_chipchat_16_mca_device; /* Ensoniq AudioPCI */ extern const device_t es1371_device; extern const device_t es1371_onboard_device; +extern const device_t es1373_device; +extern const device_t es1373_onboard_device; +extern const device_t ct5880_device; +extern const device_t ct5880_onboard_device; /* Gravis UltraSound and UltraSound Max */ extern const device_t gus_device; diff --git a/src/include/86box/timer.h b/src/include/86box/timer.h index 91f903a0fb..25aff6b2fb 100644 --- a/src/include/86box/timer.h +++ b/src/include/86box/timer.h @@ -185,6 +185,9 @@ timer_set_p(pc_timer_t *timer, void *priv) extern void timer_stop(pc_timer_t *timer); extern void timer_on_auto(pc_timer_t *timer, double period); +/* Change TSC, taking into account the timers. */ +extern void timer_set_new_tsc(uint64_t new_tsc); + #ifdef __cplusplus } #endif diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index ac4085089b..d834a6f424 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -42,9 +42,11 @@ typedef union { typedef struct ibm8514_t { rom_t bios_rom; rom_t bios_rom2; + rom_t bios_rom3; hwcursor8514_t hwcursor; hwcursor8514_t hwcursor_latch; uint8_t pos_regs[8]; + char *rom_path; int force_old_addr; int type; @@ -56,6 +58,7 @@ typedef struct ibm8514_t { uint32_t vram_size; uint32_t vram_mask; uint32_t pallook[512]; + uint32_t bios_addr; PALETTE vgapal; uint8_t hwcursor_oddeven; diff --git a/src/include/86box/vid_ati_mach8.h b/src/include/86box/vid_ati_mach8.h index 7b5862f35e..a254329201 100644 --- a/src/include/86box/vid_ati_mach8.h +++ b/src/include/86box/vid_ati_mach8.h @@ -74,6 +74,7 @@ typedef struct mach_t { uint16_t shadow_set; uint16_t shadow_cntl; int ext_on[2]; + int extended_mode; int compat_mode; struct { diff --git a/src/include/86box/vid_cga.h b/src/include/86box/vid_cga.h index 5b6a2dea24..a503d12bab 100644 --- a/src/include/86box/vid_cga.h +++ b/src/include/86box/vid_cga.h @@ -31,6 +31,8 @@ typedef struct cga_t { uint8_t cgamode; uint8_t cgacol; + uint8_t lp_strobe; + int fontbase; int linepos; int displine; diff --git a/src/include/86box/vid_cga_comp.h b/src/include/86box/vid_cga_comp.h index 2911452911..609e6d813c 100644 --- a/src/include/86box/vid_cga_comp.h +++ b/src/include/86box/vid_cga_comp.h @@ -26,6 +26,6 @@ void update_cga16_color(uint8_t cgamode); void cga_comp_init(int revision); -Bit32u *Composite_Process(uint8_t cgamode, uint8_t border, uint32_t blocks /*, bool doublewidth*/, uint32_t *TempLine); +uint32_t *Composite_Process(uint8_t cgamode, uint8_t border, uint32_t blocks /*, bool doublewidth*/, uint32_t *TempLine); #endif /*VIDEO_CGA_COMP_H*/ diff --git a/src/include/86box/vid_ogc.h b/src/include/86box/vid_ogc.h index 839769e69b..efafb180ed 100644 --- a/src/include/86box/vid_ogc.h +++ b/src/include/86box/vid_ogc.h @@ -23,6 +23,7 @@ typedef struct ogc_t { cga_t cga; + uint16_t ctrl_addr; /* unused in OGC, required for M19 video card structure idiom */ uint8_t ctrl_3dd; uint8_t ctrl_3de; diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 9eecebf2c3..18b7b672ae 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -78,6 +78,7 @@ typedef struct svga_t { uint8_t overlay_oddeven; uint8_t fcr; uint8_t hblank_overscan; + uint8_t vidsys_ena; int dac_addr; int dac_pos; @@ -86,6 +87,7 @@ typedef struct svga_t { int dac_b; int vtotal; int dispend; + int vdisp; int vsyncstart; int split; int vblankstart; @@ -169,9 +171,11 @@ typedef struct svga_t { pc_timer_t timer; pc_timer_t timer8514; + pc_timer_t timer_xga; double clock; double clock8514; + double clock_xga; double multiplier; @@ -199,6 +203,7 @@ typedef struct svga_t { void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); float (*getclock)(int clock, void *priv); + float (*getclock8514)(int clock, void *priv); /* Called when VC=R18 and friends. If this returns zero then MA resetting is skipped. Matrox Mystique in Power mode reuses this counter for @@ -288,31 +293,41 @@ typedef struct svga_t { void * dev8514; void * ext8514; + void * clock_gen8514; void * xga; } svga_t; -extern int vga_on; - -extern void ibm8514_poll(void *priv); -extern void ibm8514_recalctimings(svga_t *svga); -extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv); -extern void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *priv); -extern int ibm8514_cpu_src(svga_t *svga); -extern int ibm8514_cpu_dest(svga_t *svga); -extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint32_t val, int len); -extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len); -extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len); +extern int vga_on; + +extern void ibm8514_poll(void *priv); +extern void ibm8514_recalctimings(svga_t *svga); +extern uint8_t ibm8514_ramdac_in(uint16_t port, void *priv); +extern void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *priv); +extern void ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len); +extern void ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len); +extern uint16_t ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len); +extern uint8_t ibm8514_accel_in(uint16_t port, svga_t *svga); +extern int ibm8514_cpu_src(svga_t *svga); +extern int ibm8514_cpu_dest(svga_t *svga); +extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint32_t val, int len); +extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len); +extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len); #ifdef ATI_8514_ULTRA -extern void ati8514_recalctimings(svga_t *svga); -extern uint8_t ati8514_mca_read(int port, void *priv); -extern void ati8514_mca_write(int port, uint8_t val, void *priv); -extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); +extern void ati8514_recalctimings(svga_t *svga); +extern uint8_t ati8514_mca_read(int port, void *priv); +extern void ati8514_mca_write(int port, uint8_t val, void *priv); +extern void ati8514_pos_write(uint16_t port, uint8_t val, void *priv); +extern void ati8514_init(svga_t *svga, void *ext8514, void *dev8514); #endif -extern void xga_poll(void *priv, svga_t *svga); +extern void xga_write_test(uint32_t addr, uint8_t val, void *priv); +extern uint8_t xga_read_test(uint32_t addr, void *priv); +extern void xga_poll(void *priv); extern void xga_recalctimings(svga_t *svga); +extern uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write); + extern int svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, void (*recalctimings_ex)(struct svga_t *svga), uint8_t (*video_in)(uint16_t addr, void *priv), diff --git a/src/include/86box/vid_svga_render.h b/src/include/86box/vid_svga_render.h index 224d96c8e7..babac7592b 100644 --- a/src/include/86box/vid_svga_render.h +++ b/src/include/86box/vid_svga_render.h @@ -48,6 +48,8 @@ extern void svga_render_text_80_ksc5601(svga_t *svga); extern void svga_render_2bpp_lowres(svga_t *svga); extern void svga_render_2bpp_highres(svga_t *svga); +extern void svga_render_2bpp_s3_lowres(svga_t *svga); +extern void svga_render_2bpp_s3_highres(svga_t *svga); extern void svga_render_2bpp_headland_highres(svga_t *svga); extern void svga_render_4bpp_lowres(svga_t *svga); extern void svga_render_4bpp_highres(svga_t *svga); diff --git a/src/include/86box/vid_vga.h b/src/include/86box/vid_vga.h index bc552b2857..0ffbeb4cd3 100644 --- a/src/include/86box/vid_vga.h +++ b/src/include/86box/vid_vga.h @@ -28,9 +28,7 @@ typedef struct vga_t { rom_t bios_rom; } vga_t; -static video_timings_t timing_vga = { VIDEO_ISA, 8, 16, 32, 8, 16, 32 }; - -void vga_out(uint16_t addr, uint8_t val, void *priv); -uint8_t vga_in(uint16_t addr, void *priv); +extern void vga_out(uint16_t addr, uint8_t val, void *priv); +extern uint8_t vga_in(uint16_t addr, void *priv); #endif /*VIDEO_VGA_H*/ diff --git a/src/include/86box/vid_voodoo_common.h b/src/include/86box/vid_voodoo_common.h index 96865ac6d9..5ab63ec3af 100644 --- a/src/include/86box/vid_voodoo_common.h +++ b/src/include/86box/vid_voodoo_common.h @@ -408,6 +408,7 @@ typedef struct voodoo_t { atomic_int cmd_read; atomic_int cmd_written; atomic_int cmd_written_fifo; + atomic_int cmd_written_fifo_2; voodoo_params_t params_buffer[PARAM_SIZE]; atomic_int params_read_idx[4]; @@ -426,7 +427,20 @@ typedef struct voodoo_t { uint32_t cmdfifo_amax; int cmdfifo_holecount; - atomic_uint cmd_status; + uint32_t cmdfifo_base_2; + uint32_t cmdfifo_end_2; + uint32_t cmdfifo_size_2; + int cmdfifo_rp_2; + int cmdfifo_ret_addr_2; + int cmdfifo_in_sub_2; + atomic_int cmdfifo_depth_rd_2; + atomic_int cmdfifo_depth_wr_2; + atomic_int cmdfifo_enabled_2; + uint32_t cmdfifo_amin_2; + uint32_t cmdfifo_amax_2; + int cmdfifo_holecount_2; + + atomic_uint cmd_status, cmd_status_2; uint32_t sSetupMode; vert_t verts[4]; diff --git a/src/include/86box/vid_voodoo_regs.h b/src/include/86box/vid_voodoo_regs.h index f05029a8dd..6aeb98bccf 100644 --- a/src/include/86box/vid_voodoo_regs.h +++ b/src/include/86box/vid_voodoo_regs.h @@ -338,17 +338,22 @@ enum { }; enum { - LFB_FORMAT_RGB565 = 0, - LFB_FORMAT_RGB555 = 1, - LFB_FORMAT_ARGB1555 = 2, - LFB_FORMAT_ARGB8888 = 5, - LFB_FORMAT_DEPTH = 15, - LFB_FORMAT_MASK = 15 + LFB_FORMAT_RGB565 = 0, + LFB_FORMAT_RGB555 = 1, + LFB_FORMAT_ARGB1555 = 2, + LFB_FORMAT_XRGB8888 = 4, + LFB_FORMAT_ARGB8888 = 5, + LFB_FORMAT_DEPTH_RGB565 = 12, + LFB_FORMAT_DEPTH_RGB555 = 13, + LFB_FORMAT_DEPTH_ARGB1555 = 14, + LFB_FORMAT_DEPTH = 15, + LFB_FORMAT_MASK = 15 }; enum { LFB_WRITE_COLOUR = 1, - LFB_WRITE_DEPTH = 2 + LFB_WRITE_DEPTH = 2, + LFB_WRITE_BOTH = 4 }; enum { diff --git a/src/include/86box/vid_xga.h b/src/include/86box/vid_xga.h index e5248b309a..90a3c69aa9 100644 --- a/src/include/86box/vid_xga.h +++ b/src/include/86box/vid_xga.h @@ -31,10 +31,12 @@ typedef struct xga_hwcursor_t { } xga_hwcursor_t; typedef struct xga_t { + mem_mapping_t membios_mapping; mem_mapping_t memio_mapping; mem_mapping_t linear_mapping; mem_mapping_t video_mapping; rom_t bios_rom; + rom_t membios_rom; rom_t vga_bios_rom; xga_hwcursor_t hwcursor; xga_hwcursor_t hwcursor_latch; @@ -47,6 +49,8 @@ typedef struct xga_t { uint8_t pos_regs[8]; uint8_t disp_addr; + uint8_t dac_mask; + uint8_t dac_status; uint8_t cfg_reg; uint8_t instance; uint8_t op_mode; @@ -85,6 +89,8 @@ typedef struct xga_t { uint8_t instance_isa; uint8_t instance_num; uint8_t ext_mem_addr; + uint8_t vga_post; + uint8_t addr_test; uint8_t *vram; uint8_t *changedvram; @@ -106,6 +112,10 @@ typedef struct xga_t { uint16_t old_pal_addr_idx; uint16_t sprite_pal_addr_idx_prefetch; + int dac_addr; + int dac_pos; + int dac_r; + int dac_g; int v_total; int dispend; int v_syncstart; @@ -161,6 +171,9 @@ typedef struct xga_t { uint32_t write_bank; uint32_t px_map_base; uint32_t pallook[512]; + uint32_t bios_diag; + + PALETTE xgapal; uint64_t dispontime; uint64_t dispofftime; diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 1c8b610153..9ee7105922 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -326,13 +326,14 @@ extern const device_t ati18800_device; /* ATi 28800 */ extern const device_t ati28800_device; +extern const device_t ati28800_wonder1024d_xl_plus_device; extern const device_t ati28800k_device; extern const device_t ati28800k_spc4620p_device; extern const device_t ati28800k_spc6033p_device; extern const device_t compaq_ati28800_device; -# if defined(DEV_BRANCH) && defined(USE_XL24) +# ifdef USE_XL24 extern const device_t ati28800_wonderxl24_device; -# endif +# endif /* USE_XL24 */ /* Bochs */ extern const device_t bochs_svga_device; @@ -446,13 +447,16 @@ extern const device_t millennium_device; extern const device_t mystique_device; extern const device_t mystique_220_device; extern const device_t millennium_ii_device; +#ifdef USE_G100 extern const device_t productiva_g100_device; +#endif /* USE_G100 */ /* Oak OTI-0x7 */ extern const device_t oti037c_device; extern const device_t oti067_device; extern const device_t oti067_acer386_device; extern const device_t oti067_ama932j_device; +extern const device_t oti077_acer100t_device; extern const device_t oti077_device; /* Paradise/WD (S)VGA */ @@ -507,15 +511,15 @@ extern const device_t s3_phoenix_vision864_pci_device; extern const device_t s3_phoenix_vision864_vlb_device; extern const device_t s3_9fx_531_pci_device; extern const device_t s3_phoenix_vision868_pci_device; -extern const device_t s3_phoenix_vision868_vlb_device; extern const device_t s3_diamond_stealth64_pci_device; extern const device_t s3_diamond_stealth64_vlb_device; extern const device_t s3_diamond_stealth64_964_pci_device; extern const device_t s3_diamond_stealth64_964_vlb_device; +extern const device_t s3_diamond_stealth64_968_pci_device; +extern const device_t s3_diamond_stealth64_968_vlb_device; extern const device_t s3_mirovideo_40sv_ergo_968_pci_device; extern const device_t s3_9fx_771_pci_device; extern const device_t s3_phoenix_vision968_pci_device; -extern const device_t s3_phoenix_vision968_vlb_device; extern const device_t s3_spea_mercury_p64v_pci_device; extern const device_t s3_elsa_winner2000_pro_x_964_pci_device; extern const device_t s3_elsa_winner2000_pro_x_pci_device; @@ -524,10 +528,13 @@ extern const device_t s3_trio64v2_dx_onboard_pci_device; /* S3 ViRGE */ extern const device_t s3_virge_325_pci_device; +extern const device_t s3_virge_325_onboard_pci_device; extern const device_t s3_diamond_stealth_2000_pci_device; +extern const device_t s3_mirocrystal_3d_pci_device; extern const device_t s3_diamond_stealth_3000_pci_device; extern const device_t s3_stb_velocity_3d_pci_device; extern const device_t s3_virge_375_pci_device; +extern const device_t s3_virge_375_onboard_pci_device; extern const device_t s3_diamond_stealth_2000pro_pci_device; extern const device_t s3_virge_385_pci_device; extern const device_t s3_virge_357_pci_device; diff --git a/src/include/slirp/libslirp-version.h b/src/include/slirp/libslirp-version.h deleted file mode 100644 index b689069573..0000000000 --- a/src/include/slirp/libslirp-version.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#ifndef LIBSLIRP_VERSION_H_ -#define LIBSLIRP_VERSION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define SLIRP_MAJOR_VERSION 4 -#define SLIRP_MINOR_VERSION 7 -#define SLIRP_MICRO_VERSION 0 -#define SLIRP_VERSION_STRING "4.7.0-86Box" - -#define SLIRP_CHECK_VERSION(major,minor,micro) \ - (SLIRP_MAJOR_VERSION > (major) || \ - (SLIRP_MAJOR_VERSION == (major) && SLIRP_MINOR_VERSION > (minor)) || \ - (SLIRP_MAJOR_VERSION == (major) && SLIRP_MINOR_VERSION == (minor) && \ - SLIRP_MICRO_VERSION >= (micro))) - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LIBSLIRP_VERSION_H_ */ diff --git a/src/include/slirp/libslirp.h b/src/include/slirp/libslirp.h deleted file mode 100644 index 7a6c9a4da4..0000000000 --- a/src/include/slirp/libslirp.h +++ /dev/null @@ -1,273 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -#ifndef LIBSLIRP_H -#define LIBSLIRP_H - -#include -#include -#include - -#ifdef _WIN32 -#include -#include -#include -#else -#include -#include -#endif - -#include "libslirp-version.h" - -/* Windows does not define ssize_t, so we need to define it here. */ -#ifndef _SSIZE_T_DEFINED -# define _SSIZE_T_DEFINED -# undef ssize_t -# ifdef _WIN64 -# define ssize_t int64_t -# else -# define ssize_t int32_t -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Opaque structure containing the slirp state */ -typedef struct Slirp Slirp; - -/* Flags passed to SlirpAddPollCb and to be returned by SlirpGetREventsCb. */ -enum { - SLIRP_POLL_IN = 1 << 0, - SLIRP_POLL_OUT = 1 << 1, - SLIRP_POLL_PRI = 1 << 2, - SLIRP_POLL_ERR = 1 << 3, - SLIRP_POLL_HUP = 1 << 4, -}; - -typedef ssize_t (*SlirpReadCb)(void *buf, size_t len, void *opaque); -typedef ssize_t (*SlirpWriteCb)(const void *buf, size_t len, void *opaque); -typedef void (*SlirpTimerCb)(void *opaque); -typedef int (*SlirpAddPollCb)(int fd, int events, void *opaque); -typedef int (*SlirpGetREventsCb)(int idx, void *opaque); - -typedef enum SlirpTimerId { - SLIRP_TIMER_RA, - SLIRP_TIMER_NUM, -} SlirpTimerId; - -/* - * Callbacks from slirp, to be set by the application. - * - * The opaque parameter is set to the opaque pointer given in the slirp_new / - * slirp_init call. - */ -typedef struct SlirpCb { - /* - * Send an ethernet frame to the guest network. The opaque parameter is the - * one given to slirp_init(). If the guest is not ready to receive a frame, - * the function can just drop the data. TCP will then handle retransmissions - * at a lower pace. - * <0 reports an IO error. - */ - SlirpWriteCb send_packet; - /* Print a message for an error due to guest misbehavior. */ - void (*guest_error)(const char *msg, void *opaque); - /* Return the virtual clock value in nanoseconds */ - int64_t (*clock_get_ns)(void *opaque); - /* Create a new timer with the given callback and opaque data. Not - * needed if timer_new_opaque is provided. */ - void *(*timer_new)(SlirpTimerCb cb, void *cb_opaque, void *opaque); - /* Remove and free a timer */ - void (*timer_free)(void *timer, void *opaque); - /* Modify a timer to expire at @expire_time (ms) */ - void (*timer_mod)(void *timer, int64_t expire_time, void *opaque); - /* Register a fd for future polling */ - void (*register_poll_fd)(int fd, void *opaque); - /* Unregister a fd */ - void (*unregister_poll_fd)(int fd, void *opaque); - /* Kick the io-thread, to signal that new events may be processed because some TCP buffer - * can now receive more data, i.e. slirp_socket_can_recv will return 1. */ - void (*notify)(void *opaque); - - /* - * Fields introduced in SlirpConfig version 4 begin - */ - - /* Initialization has completed and a Slirp* has been created. */ - void (*init_completed)(Slirp *slirp, void *opaque); - /* Create a new timer. When the timer fires, the application passes - * the SlirpTimerId and cb_opaque to slirp_handle_timer. */ - void *(*timer_new_opaque)(SlirpTimerId id, void *cb_opaque, void *opaque); -} SlirpCb; - -#define SLIRP_CONFIG_VERSION_MIN 1 -#define SLIRP_CONFIG_VERSION_MAX 4 - -typedef struct SlirpConfig { - /* Version must be provided */ - uint32_t version; - /* - * Fields introduced in SlirpConfig version 1 begin - */ - int restricted; - bool in_enabled; - struct in_addr vnetwork; - struct in_addr vnetmask; - struct in_addr vhost; - bool in6_enabled; - struct in6_addr vprefix_addr6; - uint8_t vprefix_len; - struct in6_addr vhost6; - const char *vhostname; - const char *tftp_server_name; - const char *tftp_path; - const char *bootfile; - struct in_addr vdhcp_start; - struct in_addr vnameserver; - struct in6_addr vnameserver6; - const char **vdnssearch; - const char *vdomainname; - /* Default: IF_MTU_DEFAULT */ - size_t if_mtu; - /* Default: IF_MRU_DEFAULT */ - size_t if_mru; - /* Prohibit connecting to 127.0.0.1:* */ - bool disable_host_loopback; - /* - * Enable emulation code (*warning*: this code isn't safe, it is not - * recommended to enable it) - */ - bool enable_emu; - /* - * Fields introduced in SlirpConfig version 2 begin - */ - struct sockaddr_in *outbound_addr; - struct sockaddr_in6 *outbound_addr6; - /* - * Fields introduced in SlirpConfig version 3 begin - */ - bool disable_dns; /* slirp will not redirect/serve any DNS packet */ - /* - * Fields introduced in SlirpConfig version 4 begin - */ - bool disable_dhcp; /* slirp will not reply to any DHCP requests */ -} SlirpConfig; - -/* Create a new instance of a slirp stack */ -Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, - void *opaque); -/* slirp_init is deprecated in favor of slirp_new */ -Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork, - struct in_addr vnetmask, struct in_addr vhost, - bool in6_enabled, struct in6_addr vprefix_addr6, - uint8_t vprefix_len, struct in6_addr vhost6, - const char *vhostname, const char *tftp_server_name, - const char *tftp_path, const char *bootfile, - struct in_addr vdhcp_start, struct in_addr vnameserver, - struct in6_addr vnameserver6, const char **vdnssearch, - const char *vdomainname, const SlirpCb *callbacks, - void *opaque); -/* Shut down an instance of a slirp stack */ -void slirp_cleanup(Slirp *slirp); - -/* This is called by the application when it is about to sleep through poll(). - * *timeout is set to the amount of virtual time (in ms) that the application intends to - * wait (UINT32_MAX if infinite). slirp_pollfds_fill updates it according to - * e.g. TCP timers, so the application knows it should sleep a smaller amount of - * time. slirp_pollfds_fill calls add_poll for each file descriptor - * that should be monitored along the sleep. The opaque pointer is passed as - * such to add_poll, and add_poll returns an index. */ -void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout, - SlirpAddPollCb add_poll, void *opaque); - -/* This is called by the application after sleeping, to report which file - * descriptors are available. slirp_pollfds_poll calls get_revents on each file - * descriptor, giving it the index that add_poll returned during the - * slirp_pollfds_fill call, to know whether the descriptor is available for - * read/write/etc. (SLIRP_POLL_*) - * select_error should be passed 1 if poll() returned an error. */ -void slirp_pollfds_poll(Slirp *slirp, int select_error, - SlirpGetREventsCb get_revents, void *opaque); - -/* This is called by the application when the guest emits a packet on the - * guest network, to be interpreted by slirp. */ -void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len); - -/* This is called by the application when a timer expires, if it provides - * the timer_new_opaque callback. It is not needed if the application only - * uses timer_new. */ -void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque); - -/* These set up / remove port forwarding between a host port in the real world - * and the guest network. */ -int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, - int host_port, struct in_addr guest_addr, int guest_port); -int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, - int host_port); - -#define SLIRP_HOSTFWD_UDP 1 -#define SLIRP_HOSTFWD_V6ONLY 2 -int slirp_add_hostxfwd(Slirp *slirp, - const struct sockaddr *haddr, socklen_t haddrlen, - const struct sockaddr *gaddr, socklen_t gaddrlen, - int flags); -int slirp_remove_hostxfwd(Slirp *slirp, - const struct sockaddr *haddr, socklen_t haddrlen, - int flags); - -/* Set up port forwarding between a port in the guest network and a - * command running on the host */ -int slirp_add_exec(Slirp *slirp, const char *cmdline, - struct in_addr *guest_addr, int guest_port); -/* Set up port forwarding between a port in the guest network and a - * Unix port on the host */ -int slirp_add_unix(Slirp *slirp, const char *unixsock, - struct in_addr *guest_addr, int guest_port); -/* Set up port forwarding between a port in the guest network and a - * callback that will receive the data coming from the port */ -int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, - struct in_addr *guest_addr, int guest_port); - -/* TODO: rather identify a guestfwd through an opaque pointer instead of through - * the guest_addr */ - -/* This is called by the application for a guestfwd, to determine how much data - * can be received by the forwarded port through a call to slirp_socket_recv. */ -size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr, - int guest_port); -/* This is called by the application for a guestfwd, to provide the data to be - * sent on the forwarded port */ -void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port, - const uint8_t *buf, int size); - -/* Remove entries added by slirp_add_exec, slirp_add_unix or slirp_add_guestfwd */ -int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr, - int guest_port); - -/* Return a human-readable state of the slirp stack */ -char *slirp_connection_info(Slirp *slirp); - -/* Return a human-readable state of the NDP/ARP tables */ -char *slirp_neighbor_info(Slirp *slirp); - -/* Save the slirp state through the write_cb. The opaque pointer is passed as - * such to the write_cb. */ -void slirp_state_save(Slirp *s, SlirpWriteCb write_cb, void *opaque); - -/* Returns the version of the slirp state, to be saved along the state */ -int slirp_state_version(void); - -/* Load the slirp state through the read_cb. The opaque pointer is passed as - * such to the read_cb. The version should be given as it was obtained from - * slirp_state_version when slirp_state_save was called. */ -int slirp_state_load(Slirp *s, int version_id, SlirpReadCb read_cb, - void *opaque); - -/* Return the version of the slirp implementation */ -const char *slirp_version_string(void); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LIBSLIRP_H */ diff --git a/src/ini.c b/src/ini.c index a792d356bb..6162457864 100644 --- a/src/ini.c +++ b/src/ini.c @@ -546,7 +546,7 @@ ini_section_get_int(ini_section_t self, const char *name, int def) { section_t *section = (section_t *) self; const entry_t *entry; - int value; + int value = 0; if (section == NULL) return def; @@ -565,7 +565,7 @@ ini_section_get_uint(ini_section_t self, const char *name, uint32_t def) { section_t *section = (section_t *) self; const entry_t *entry; - uint32_t value; + uint32_t value = 0; if (section == NULL) return def; @@ -585,7 +585,7 @@ ini_section_get_float(ini_section_t self, const char *name, float def) { section_t *section = (section_t *) self; const entry_t *entry; - float value; + float value = 0; if (section == NULL) return def; @@ -605,7 +605,7 @@ ini_section_get_double(ini_section_t self, const char *name, double def) { section_t *section = (section_t *) self; const entry_t *entry; - double value; + double value = 0; if (section == NULL) return def; @@ -624,7 +624,7 @@ ini_section_get_hex16(ini_section_t self, const char *name, int def) { section_t *section = (section_t *) self; const entry_t *entry; - unsigned int value; + unsigned int value = 0; if (section == NULL) return def; @@ -643,7 +643,7 @@ ini_section_get_hex20(ini_section_t self, const char *name, int def) { section_t *section = (section_t *) self; const entry_t *entry; - unsigned int value; + unsigned int value = 0; if (section == NULL) return def; diff --git a/src/lpt.c b/src/lpt.c index 419e5ad3d5..3f1c5eb7b6 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -42,6 +42,9 @@ static const struct { {"text_prt", &lpt_prt_text_device }, {"dot_matrix", &lpt_prt_escp_device }, {"postscript", &lpt_prt_ps_device }, +#ifdef USE_PCL + {"pcl", &lpt_prt_pcl_device }, +#endif {"plip", &lpt_plip_device }, {"dongle_savquest", &lpt_hasp_savquest_device }, {"", NULL } diff --git a/src/mac/CMakeLists.txt b/src/mac/CMakeLists.txt index bbdf1d5d59..0562ca01d0 100644 --- a/src/mac/CMakeLists.txt +++ b/src/mac/CMakeLists.txt @@ -11,10 +11,12 @@ # Authors: dob205, # Jerome Vernet # David Hrdlička, +# Jasmine Iwanek, # # Copyright 2021 dob205. # Copyright 2021 Jerome Vernet. # Copyright 2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # # Pick the bundle icon depending on the release channel diff --git a/src/machine/CMakeLists.txt b/src/machine/CMakeLists.txt index ecc374e664..55e0e01970 100644 --- a/src/machine/CMakeLists.txt +++ b/src/machine/CMakeLists.txt @@ -9,20 +9,51 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c +add_library(mch OBJECT + machine.c + machine_table.c + m_xt.c + m_xt_compaq.c m_xt_philips.c - m_xt_t1000.c m_xt_t1000_vid.c m_xt_xi8088.c m_xt_zenith.c m_pcjr.c - m_amstrad.c m_europc.c m_elt.c m_xt_olivetti.c m_tandy.c m_v86p.c - m_at.c m_at_commodore.c - m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c - m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c - m_at_socket4.c m_at_socket5.c m_at_socket7_3v.c m_at_socket7.c - m_at_sockets7.c m_at_socket8.c m_at_slot1.c m_at_slot2.c m_at_socket370.c - m_at_misc.c) + m_xt_t1000.c + m_xt_t1000_vid.c + m_xt_xi8088.c + m_xt_zenith.c + m_pcjr.c + m_amstrad.c + m_europc.c + m_elt.c + m_xt_olivetti.c + m_tandy.c + m_v86p.c + m_at.c + m_at_commodore.c + m_at_t3100e.c + m_at_t3100e_vid.c + m_ps1.c + m_ps1_hdc.c + m_ps2_isa.c + m_ps2_mca.c + m_at_compaq.c + m_at_286_386sx.c + m_at_386dx_486.c + m_at_socket4.c + m_at_socket5.c + m_at_socket7_3v.c + m_at_socket7.c + m_at_sockets7.c + m_at_socket8.c + m_at_slot1.c + m_at_slot2.c + m_at_socket370.c + m_at_misc.c +) if(AN430TX) target_compile_definitions(mch PRIVATE USE_AN430TX) diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index dfeb1fa0f2..530362b895 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -2350,133 +2350,518 @@ ams_read(uint16_t port, void *priv) static const scancode scancode_pc200[512] = { // clang-format off - { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ - { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ - { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ - { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ - { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ - { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ - { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ - { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ - { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ - { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ - { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ - { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ - { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ - { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ - { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ - { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ - { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ - { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ - { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ - { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ - { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ - { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ - { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ - { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ - { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ - { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ - { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ - { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ - { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ - { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ - { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ - { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ - - { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ - { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ - { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ - { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ - { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ - { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ - { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ - { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ - { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ - { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ - { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ - { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ - { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ - { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ - { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ - { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ - { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ - { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ - { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ - { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ - { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ - { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ - { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ - { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ - { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ - { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ - { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ - { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ - { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ - { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ - - { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ - { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ - { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ - { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ - { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ - { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ - { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ - { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ - { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ - { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ - { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ - { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ - { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ - { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ - { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ - { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ - { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ - { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ - { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ - { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ - { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ - { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ - { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ - { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ - { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ - { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 012 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0x54, 0 }, .brk = { 0xd4, 0 } }, /* 054 */ + { .mk = { 0x55, 0 }, .brk = { 0xd5, 0 } }, /* 055 */ + { .mk = { 0x56, 0 }, .brk = { 0xd6, 0 } }, /* 056 */ + { .mk = { 0x57, 0 }, .brk = { 0xd7, 0 } }, /* 057 */ + { .mk = { 0x58, 0 }, .brk = { 0xd8, 0 } }, /* 058 */ + { .mk = { 0x59, 0 }, .brk = { 0xd9, 0 } }, /* 059 */ + { .mk = { 0x5a, 0 }, .brk = { 0xda, 0 } }, /* 05a */ + { .mk = { 0x5b, 0 }, .brk = { 0xdb, 0 } }, /* 05b */ + { .mk = { 0x5c, 0 }, .brk = { 0xdc, 0 } }, /* 05c */ + { .mk = { 0x5d, 0 }, .brk = { 0xdd, 0 } }, /* 05d */ + { .mk = { 0x5e, 0 }, .brk = { 0xde, 0 } }, /* 05e */ + { .mk = { 0x5f, 0 }, .brk = { 0xdf, 0 } }, /* 05f */ + { .mk = { 0x60, 0 }, .brk = { 0xe0, 0 } }, /* 060 */ + { .mk = { 0x61, 0 }, .brk = { 0xe1, 0 } }, /* 061 */ + { .mk = { 0x62, 0 }, .brk = { 0xe2, 0 } }, /* 062 */ + { .mk = { 0x63, 0 }, .brk = { 0xe3, 0 } }, /* 063 */ + { .mk = { 0x64, 0 }, .brk = { 0xe4, 0 } }, /* 064 */ + { .mk = { 0x65, 0 }, .brk = { 0xe5, 0 } }, /* 065 */ + { .mk = { 0x66, 0 }, .brk = { 0xe6, 0 } }, /* 066 */ + { .mk = { 0x67, 0 }, .brk = { 0xe7, 0 } }, /* 067 */ + { .mk = { 0x68, 0 }, .brk = { 0xe8, 0 } }, /* 068 */ + { .mk = { 0x69, 0 }, .brk = { 0xe9, 0 } }, /* 069 */ + { .mk = { 0x6a, 0 }, .brk = { 0xea, 0 } }, /* 06a */ + { .mk = { 0x6b, 0 }, .brk = { 0xeb, 0 } }, /* 06b */ + { .mk = { 0x6c, 0 }, .brk = { 0xec, 0 } }, /* 06c */ + { .mk = { 0x6d, 0 }, .brk = { 0xed, 0 } }, /* 06d */ + { .mk = { 0x6e, 0 }, .brk = { 0xee, 0 } }, /* 06e */ + { .mk = { 0x6f, 0 }, .brk = { 0xef, 0 } }, /* 06f */ + { .mk = { 0x70, 0 }, .brk = { 0xf0, 0 } }, /* 070 */ + { .mk = { 0x71, 0 }, .brk = { 0xf1, 0 } }, /* 071 */ + { .mk = { 0x72, 0 }, .brk = { 0xf2, 0 } }, /* 072 */ + { .mk = { 0x73, 0 }, .brk = { 0xf3, 0 } }, /* 073 */ + { .mk = { 0x74, 0 }, .brk = { 0xf4, 0 } }, /* 074 */ + { .mk = { 0x75, 0 }, .brk = { 0xf5, 0 } }, /* 075 */ + { .mk = { 0x76, 0 }, .brk = { 0xf6, 0 } }, /* 076 */ + { .mk = { 0x77, 0 }, .brk = { 0xf7, 0 } }, /* 077 */ + { .mk = { 0x78, 0 }, .brk = { 0xf8, 0 } }, /* 078 */ + { .mk = { 0x79, 0 }, .brk = { 0xf9, 0 } }, /* 079 */ + { .mk = { 0x7a, 0 }, .brk = { 0xfa, 0 } }, /* 07a */ + { .mk = { 0x7b, 0 }, .brk = { 0xfb, 0 } }, /* 07b */ + { .mk = { 0x7c, 0 }, .brk = { 0xfc, 0 } }, /* 07c */ + { .mk = { 0x7d, 0 }, .brk = { 0xfd, 0 } }, /* 07d */ + { .mk = { 0x7e, 0 }, .brk = { 0xfe, 0 } }, /* 07e */ + { .mk = { 0x7f, 0 }, .brk = { 0xff, 0 } }, /* 07f */ + { .mk = { 0x80, 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0x81, 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0x82, 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0x85, 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0x86, 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0x87, 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0x88, 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0x89, 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0x8a, 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0x8b, 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0x8c, 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0x8d, 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0x8e, 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0x8f, 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0x90, 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0x91, 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0x92, 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0x93, 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0x94, 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0x95, 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0x96, 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0x97, 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0x98, 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0x99, 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0x9a, 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0x9b, 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0x9c, 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0x9d, 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0x9e, 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0x9f, 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0xa0, 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0xa1, 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0xa2, 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0xa3, 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0xa4, 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0xa5, 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0xa6, 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0xa7, 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0xa8, 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0xa9, 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0xaa, 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0xab, 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0xac, 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0xad, 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0xae, 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0xaf, 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0xb0, 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0xb1, 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0xb2, 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0xb3, 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0xb4, 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0xb5, 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0xb6, 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0xb7, 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0xb8, 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0xb9, 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0xba, 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0xbb, 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0xbc, 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0xbd, 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0xbe, 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0xbf, 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0xc0, 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0xc1, 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0xc2, 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0xc3, 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0xc4, 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0xc5, 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0xc6, 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0xc7, 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0xc8, 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0xc9, 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0xca, 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0xcb, 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0xcc, 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0xcd, 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0xce, 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0xcf, 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0xd0, 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0xd1, 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0xd2, 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0xd3, 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0xd4, 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0xd5, 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0xd6, 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0xd7, 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0xd8, 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0xd9, 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0xda, 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0xdb, 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0xdc, 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0xdd, 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0xde, 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0xdf, 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0xe0, 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0xe1, 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0xe2, 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0xe3, 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0xe4, 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0xe5, 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0xe6, 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0xe7, 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0xe8, 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0xe9, 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0xea, 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0xeb, 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0xec, 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0xed, 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0xee, 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0xef, 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0xf1, 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0xf2, 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0xf3, 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0xf4, 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0xf5, 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0xf6, 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0xf7, 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0xf8, 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0xf9, 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0xfa, 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0xfb, 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0xfc, 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0xfd, 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0xfe, 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0xff, 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = {0xe1, 0x1d, 0 }, .brk = { 0xe1, 0x9d, 0 } }, /* 100 */ + { .mk = {0xe0, 0x01, 0 }, .brk = { 0xe0, 0x81, 0 } }, /* 101 */ + { .mk = {0xe0, 0x02, 0 }, .brk = { 0xe0, 0x82, 0 } }, /* 102 */ + { .mk = {0xe0, 0x03, 0 }, .brk = { 0xe0, 0x83, 0 } }, /* 103 */ + { .mk = {0xe0, 0x04, 0 }, .brk = { 0xe0, 0x84, 0 } }, /* 104 */ + { .mk = {0xe0, 0x05, 0 }, .brk = { 0xe0, 0x85, 0 } }, /* 105 */ + { .mk = {0xe0, 0x06, 0 }, .brk = { 0xe0, 0x86, 0 } }, /* 106 */ + { .mk = {0xe0, 0x07, 0 }, .brk = { 0xe0, 0x87, 0 } }, /* 107 */ + { .mk = {0xe0, 0x08, 0 }, .brk = { 0xe0, 0x88, 0 } }, /* 108 */ + { .mk = {0xe0, 0x09, 0 }, .brk = { 0xe0, 0x89, 0 } }, /* 109 */ + { .mk = {0xe0, 0x0a, 0 }, .brk = { 0xe0, 0x8a, 0 } }, /* 10a */ + { .mk = {0xe0, 0x0b, 0 }, .brk = { 0xe0, 0x8b, 0 } }, /* 10b */ + { .mk = {0xe0, 0x0c, 0 }, .brk = { 0xe0, 0x8c, 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = {0xe0, 0x0e, 0 }, .brk = { 0xe0, 0x8e, 0 } }, /* 10e */ + { .mk = {0xe0, 0x0f, 0 }, .brk = { 0xe0, 0x8f, 0 } }, /* 10f */ + { .mk = {0xe0, 0x10, 0 }, .brk = { 0xe0, 0x90, 0 } }, /* 110 */ + { .mk = {0xe0, 0x11, 0 }, .brk = { 0xe0, 0x91, 0 } }, /* 111 */ + { .mk = {0xe0, 0x12, 0 }, .brk = { 0xe0, 0x92, 0 } }, /* 112 */ + { .mk = {0xe0, 0x13, 0 }, .brk = { 0xe0, 0x93, 0 } }, /* 113 */ + { .mk = {0xe0, 0x14, 0 }, .brk = { 0xe0, 0x94, 0 } }, /* 114 */ + { .mk = {0xe0, 0x15, 0 }, .brk = { 0xe0, 0x95, 0 } }, /* 115 */ + { .mk = {0xe0, 0x16, 0 }, .brk = { 0xe0, 0x96, 0 } }, /* 116 */ + { .mk = {0xe0, 0x17, 0 }, .brk = { 0xe0, 0x97, 0 } }, /* 117 */ + { .mk = {0xe0, 0x18, 0 }, .brk = { 0xe0, 0x98, 0 } }, /* 118 */ + { .mk = {0xe0, 0x19, 0 }, .brk = { 0xe0, 0x99, 0 } }, /* 119 */ + { .mk = {0xe0, 0x1a, 0 }, .brk = { 0xe0, 0x9a, 0 } }, /* 11a */ + { .mk = {0xe0, 0x1b, 0 }, .brk = { 0xe0, 0x9b, 0 } }, /* 11b */ + { .mk = {0xe0, 0x1c, 0 }, .brk = { 0xe0, 0x9c, 0 } }, /* 11c */ + { .mk = {0xe0, 0x1d, 0 }, .brk = { 0xe0, 0x9d, 0 } }, /* 11d */ + { .mk = {0xe0, 0x1e, 0 }, .brk = { 0xe0, 0x9e, 0 } }, /* 11e */ + { .mk = {0xe0, 0x1f, 0 }, .brk = { 0xe0, 0x9f, 0 } }, /* 11f */ + { .mk = {0xe0, 0x20, 0 }, .brk = { 0xe0, 0xa0, 0 } }, /* 120 */ + { .mk = {0xe0, 0x21, 0 }, .brk = { 0xe0, 0xa1, 0 } }, /* 121 */ + { .mk = {0xe0, 0x22, 0 }, .brk = { 0xe0, 0xa2, 0 } }, /* 122 */ + { .mk = {0xe0, 0x23, 0 }, .brk = { 0xe0, 0xa3, 0 } }, /* 123 */ + { .mk = {0xe0, 0x24, 0 }, .brk = { 0xe0, 0xa4, 0 } }, /* 124 */ + { .mk = {0xe0, 0x25, 0 }, .brk = { 0xe0, 0xa5, 0 } }, /* 125 */ + { .mk = {0xe0, 0x26, 0 }, .brk = { 0xe0, 0xa6, 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = {0xe0, 0x2c, 0 }, .brk = { 0xe0, 0xac, 0 } }, /* 12c */ + { .mk = {0xe0, 0x2d, 0 }, .brk = { 0xe0, 0xad, 0 } }, /* 12d */ + { .mk = {0xe0, 0x2e, 0 }, .brk = { 0xe0, 0xae, 0 } }, /* 12e */ + { .mk = {0xe0, 0x2f, 0 }, .brk = { 0xe0, 0xaf, 0 } }, /* 12f */ + { .mk = {0xe0, 0x30, 0 }, .brk = { 0xe0, 0xb0, 0 } }, /* 130 */ + { .mk = {0xe0, 0x31, 0 }, .brk = { 0xe0, 0xb1, 0 } }, /* 131 */ + { .mk = {0xe0, 0x32, 0 }, .brk = { 0xe0, 0xb2, 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = {0xe0, 0x34, 0 }, .brk = { 0xe0, 0xb4, 0 } }, /* 134 */ + { .mk = {0xe0, 0x35, 0 }, .brk = { 0xe0, 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = {0xe0, 0x37, 0 }, .brk = { 0xe0, 0xb7, 0 } }, /* 137 */ + { .mk = {0xe0, 0x38, 0 }, .brk = { 0xe0, 0xb8, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = {0xe0, 0x3a, 0 }, .brk = { 0xe0, 0xba, 0 } }, /* 13a */ + { .mk = {0xe0, 0x3b, 0 }, .brk = { 0xe0, 0xbb, 0 } }, /* 13b */ + { .mk = {0xe0, 0x3c, 0 }, .brk = { 0xe0, 0xbc, 0 } }, /* 13c */ + { .mk = {0xe0, 0x3d, 0 }, .brk = { 0xe0, 0xbd, 0 } }, /* 13d */ + { .mk = {0xe0, 0x3e, 0 }, .brk = { 0xe0, 0xbe, 0 } }, /* 13e */ + { .mk = {0xe0, 0x3f, 0 }, .brk = { 0xe0, 0xbf, 0 } }, /* 13f */ + { .mk = {0xe0, 0x40, 0 }, .brk = { 0xe0, 0xc0, 0 } }, /* 140 */ + { .mk = {0xe0, 0x41, 0 }, .brk = { 0xe0, 0xc1, 0 } }, /* 141 */ + { .mk = {0xe0, 0x42, 0 }, .brk = { 0xe0, 0xc2, 0 } }, /* 142 */ + { .mk = {0xe0, 0x43, 0 }, .brk = { 0xe0, 0xc3, 0 } }, /* 143 */ + { .mk = {0xe0, 0x44, 0 }, .brk = { 0xe0, 0xc4, 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = {0xe0, 0x46, 0 }, .brk = { 0xe0, 0xc6, 0 } }, /* 146 */ + { .mk = {0xe0, 0x47, 0 }, .brk = { 0xe0, 0xc7, 0 } }, /* 147 */ + { .mk = {0xe0, 0x48, 0 }, .brk = { 0xe0, 0xc8, 0 } }, /* 148 */ + { .mk = {0xe0, 0x49, 0 }, .brk = { 0xe0, 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = {0xe0, 0x4b, 0 }, .brk = { 0xe0, 0xcb, 0 } }, /* 14b */ + { .mk = {0xe0, 0x4c, 0 }, .brk = { 0xe0, 0xcc, 0 } }, /* 14c */ + { .mk = {0xe0, 0x4d, 0 }, .brk = { 0xe0, 0xcd, 0 } }, /* 14d */ + { .mk = {0xe0, 0x4e, 0 }, .brk = { 0xe0, 0xce, 0 } }, /* 14e */ + { .mk = {0xe0, 0x4f, 0 }, .brk = { 0xe0, 0xcf, 0 } }, /* 14f */ + { .mk = {0xe0, 0x50, 0 }, .brk = { 0xe0, 0xd0, 0 } }, /* 150 */ + { .mk = {0xe0, 0x51, 0 }, .brk = { 0xe0, 0xd1, 0 } }, /* 151 */ + { .mk = {0xe0, 0x52, 0 }, .brk = { 0xe0, 0xd2, 0 } }, /* 152 */ + { .mk = {0xe0, 0x53, 0 }, .brk = { 0xe0, 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = {0xe0, 0x55, 0 }, .brk = { 0xe0, 0xd5, 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */ + { .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */ + { .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */ + { .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */ + { .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */ + { .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */ + { .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */ + { .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */ + { .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */ + { .mk = {0xe0, 0x62, 0 }, .brk = { 0xe0, 0xe2, 0 } }, /* 162 */ + { .mk = {0xe0, 0x63, 0 }, .brk = { 0xe0, 0xe3, 0 } }, /* 163 */ + { .mk = {0xe0, 0x64, 0 }, .brk = { 0xe0, 0xe4, 0 } }, /* 164 */ + { .mk = {0xe0, 0x65, 0 }, .brk = { 0xe0, 0xe5, 0 } }, /* 165 */ + { .mk = {0xe0, 0x66, 0 }, .brk = { 0xe0, 0xe6, 0 } }, /* 166 */ + { .mk = {0xe0, 0x67, 0 }, .brk = { 0xe0, 0xe7, 0 } }, /* 167 */ + { .mk = {0xe0, 0x68, 0 }, .brk = { 0xe0, 0xe8, 0 } }, /* 168 */ + { .mk = {0xe0, 0x69, 0 }, .brk = { 0xe0, 0xe9, 0 } }, /* 169 */ + { .mk = {0xe0, 0x6a, 0 }, .brk = { 0xe0, 0xea, 0 } }, /* 16a */ + { .mk = {0xe0, 0x6b, 0 }, .brk = { 0xe0, 0xeb, 0 } }, /* 16b */ + { .mk = {0xe0, 0x6c, 0 }, .brk = { 0xe0, 0xec, 0 } }, /* 16c */ + { .mk = {0xe0, 0x6d, 0 }, .brk = { 0xe0, 0xed, 0 } }, /* 16d */ + { .mk = {0xe0, 0x6e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = {0xe0, 0x70, 0 }, .brk = { 0xe0, 0xf0, 0 } }, /* 170 */ + { .mk = {0xe0, 0x71, 0 }, .brk = { 0xe0, 0xf1, 0 } }, /* 171 */ + { .mk = {0xe0, 0x72, 0 }, .brk = { 0xe0, 0xf2, 0 } }, /* 172 */ + { .mk = {0xe0, 0x73, 0 }, .brk = { 0xe0, 0xf3, 0 } }, /* 173 */ + { .mk = {0xe0, 0x74, 0 }, .brk = { 0xe0, 0xf4, 0 } }, /* 174 */ + { .mk = {0xe0, 0x75, 0 }, .brk = { 0xe0, 0xf5, 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = {0xe0, 0x77, 0 }, .brk = { 0xe0, 0xf7, 0 } }, /* 177 */ + { .mk = {0xe0, 0x78, 0 }, .brk = { 0xe0, 0xf8, 0 } }, /* 178 */ + { .mk = {0xe0, 0x79, 0 }, .brk = { 0xe0, 0xf9, 0 } }, /* 179 */ + { .mk = {0xe0, 0x7a, 0 }, .brk = { 0xe0, 0xfa, 0 } }, /* 17a */ + { .mk = {0xe0, 0x7b, 0 }, .brk = { 0xe0, 0xfb, 0 } }, /* 17b */ + { .mk = {0xe0, 0x7c, 0 }, .brk = { 0xe0, 0xfc, 0 } }, /* 17c */ + { .mk = {0xe0, 0x7d, 0 }, .brk = { 0xe0, 0xfd, 0 } }, /* 17d */ + { .mk = {0xe0, 0x7e, 0 }, .brk = { 0xe0, 0xfe, 0 } }, /* 17e */ + { .mk = {0xe0, 0x7f, 0 }, .brk = { 0xe0, 0xff, 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = {0xe0, 0xe1, 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = {0xe0, 0xee, 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = {0xe0, 0xf1, 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = {0xe0, 0xfe, 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = {0xe0, 0xff, 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 9fc53ebcd0..122c5cdef2 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -105,7 +105,7 @@ machine_at_ibm_common_init(const machine_t *model) mem_remap_top(384); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -252,13 +252,30 @@ machine_at_siemens_init(const machine_t *model) mem_remap_top(384); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; } -#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) +int +machine_at_wellamerastar_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved("roms/machines/wellamerastar/W_3.031_L.BIN", + "roms/machines/wellamerastar/W_3.031_H.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ibm_common_init(model); + + return ret; +} + +#ifdef USE_OPEN_AT int machine_at_openat_init(const machine_t *model) { @@ -274,4 +291,4 @@ machine_at_openat_init(const machine_t *model) return ret; } -#endif +#endif /* USE_OPEN_AT */ diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b2470bae24..995301e4f2 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -59,7 +59,7 @@ machine_at_mr286_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -70,7 +70,7 @@ machine_at_headland_common_init(int type) { device_add(&keyboard_at_ami_device); - if ((type != 2) && (fdc_type == FDC_INTERNAL)) + if ((type != 2) && (fdc_current[0] == FDC_INTERNAL)) device_add(&fdc_at_device); if (type == 2) @@ -137,7 +137,7 @@ machine_at_quadt286_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&headland_gc10x_device); @@ -160,7 +160,7 @@ machine_at_quadt386sx_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&headland_gc10x_device); @@ -183,7 +183,7 @@ machine_at_neat_init(const machine_t *model) device_add(&neat_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -204,7 +204,7 @@ machine_at_neat_ami_init(const machine_t *model) device_add(&neat_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); @@ -226,7 +226,7 @@ machine_at_px286_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&neat_device); @@ -248,7 +248,7 @@ machine_at_micronics386_init(const machine_t *model) machine_at_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -284,7 +284,7 @@ machine_at_scatsx_init(const machine_t *model) device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&scat_sx_device); @@ -303,7 +303,7 @@ machine_at_award286_init(const machine_t *model) machine_at_scat_init(model, 0, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -324,7 +324,7 @@ machine_at_gdc212m_init(const machine_t *model) machine_at_scat_init(model, 0, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -365,7 +365,7 @@ machine_at_senor_scat286_init(const machine_t *model) machine_at_scat_init(model, 0, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -386,7 +386,7 @@ machine_at_super286c_init(const machine_t *model) device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&neat_device); @@ -407,7 +407,7 @@ machine_at_super286tr_init(const machine_t *model) machine_at_scat_init(model, 0, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -426,7 +426,7 @@ machine_at_spc4200p_init(const machine_t *model) machine_at_scat_init(model, 0, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -448,7 +448,7 @@ machine_at_spc4216p_init(const machine_t *model) machine_at_scat_init(model, 1, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -471,7 +471,7 @@ machine_at_spc4620p_init(const machine_t *model) machine_at_scat_init(model, 1, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -508,7 +508,7 @@ machine_at_deskmaster286_init(const machine_t *model) machine_at_scat_init(model, 0, 1); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&ide_isa_device); @@ -533,7 +533,7 @@ machine_at_shuttle386sx_init(const machine_t *model) device_add(&intel_82335_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -557,7 +557,7 @@ machine_at_adi386sx_init(const machine_t *model) device_add(&intel_82335_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -603,7 +603,7 @@ machine_at_cmdsl386sx16_init(const machine_t *model) device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&neat_device); @@ -624,7 +624,7 @@ machine_at_scamp_common_init(const machine_t *model, int is_ps2) else device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&vlsi_scamp_device); @@ -644,7 +644,12 @@ machine_at_cmdsl386sx25_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&gd5402_onboard_device); - machine_at_scamp_common_init(model, 1); + machine_at_common_ide_init(model); + + device_add(&ali5105_device); /* The FDC is part of the ALi M5105. */ + device_add(&vl82c113_device); /* The keyboard controller is part of the VL82c113. */ + + device_add(&vlsi_scamp_device); return ret; } @@ -699,12 +704,38 @@ machine_at_awardsx_init(const machine_t *model) device_add(&opti291_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; } +int +machine_at_acer100t_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acer100t/acer386.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ps2_ide_init(model); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&ali1409_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&oti077_acer100t_device); + + device_add(&ali5105_device); + + return ret; +} + + int machine_at_arb1374_init(const machine_t *model) { @@ -871,7 +902,7 @@ machine_at_pc8_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_ncr_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -896,7 +927,7 @@ machine_at_3302_init(const machine_t *model) machine_at_common_ide_init(model); device_add(&neat_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); if (gfxcard[0] == VID_INTERNAL) @@ -928,13 +959,13 @@ machine_at_pc916sx_init(const machine_t *model) device_add(&keyboard_at_ncr_device); mem_remap_top(384); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; } -#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) +#ifdef USE_OLIVETTI int machine_at_m290_init(const machine_t *model) { @@ -950,11 +981,11 @@ machine_at_m290_init(const machine_t *model) device_add(&keyboard_at_olivetti_device); device_add(&port_6x_olivetti_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&olivetti_eva_device); return ret; } -#endif +#endif /* USE_OLIVETTI */ diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index 1a6a6db670..00a4021fe7 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -41,6 +41,7 @@ #include <86box/sio.h> #include <86box/hdc.h> #include <86box/port_6x.h> +#include <86box/port_92.h> #include <86box/video.h> #include <86box/flash.h> #include <86box/scsi_ncr53c8xx.h> @@ -63,7 +64,7 @@ machine_at_acc386_init(const machine_t *model) device_add(&acc2168_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -84,7 +85,7 @@ machine_at_asus386_init(const machine_t *model) device_add(&rabbit_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -104,7 +105,7 @@ machine_at_tandy4000_init(const machine_t *model) machine_at_common_init(model); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -117,7 +118,7 @@ machine_at_sis401_common_init(const machine_t *model) device_add(&sis_85c401_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -168,7 +169,7 @@ machine_at_av4_init(const machine_t *model) device_add(&sis_85c460_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -192,7 +193,7 @@ machine_at_valuepoint433_init(const machine_t *model) // hangs without the PS/2 device_add(&keyboard_ps2_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -213,7 +214,7 @@ machine_at_ecs386_init(const machine_t *model) machine_at_common_init(model); device_add(&cs8230_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); @@ -236,7 +237,7 @@ machine_at_spc6000a_init(const machine_t *model) machine_at_common_init_ex(model, 1); device_add(&cs8230_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&keyboard_at_ami_device); @@ -259,7 +260,7 @@ machine_at_ecs386v_init(const machine_t *model) device_add(&ali1429_device); device_add(&keyboard_ps2_intel_ami_pci_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -281,7 +282,7 @@ machine_at_rycleopardlx_init(const machine_t *model) device_add(&opti283_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -303,7 +304,7 @@ machine_at_486vchd_init(const machine_t *model) device_add(&via_vt82c49x_device); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -324,7 +325,7 @@ machine_at_cs4031_init(const machine_t *model) device_add(&cs4031_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -374,7 +375,7 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems if (gfxcard[0] == VID_INTERNAL) device_add(&gd5428_onboard_device); - device_add(&keyboard_ps2_ami_device); + device_add(&vl82c113_device); device_add(&fdc37c651_ide_device); return ret; @@ -448,7 +449,7 @@ machine_at_acerv10_init(const machine_t *model) device_add(&keyboard_ps2_acer_pci_device); device_add(&ide_isa_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -492,7 +493,7 @@ machine_at_ali1429_common_init(const machine_t *model, int is_green) device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -545,7 +546,7 @@ machine_at_opti495_init(const machine_t *model) device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -560,7 +561,7 @@ machine_at_opti495_ami_common_init(const machine_t *model) device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -612,7 +613,7 @@ machine_at_exp4349_init(const machine_t *model) device_add(&ali1429g_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; } @@ -630,7 +631,7 @@ machine_at_403tg_common_init(const machine_t *model, int nvr_hack) device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); } @@ -801,7 +802,7 @@ machine_at_sis_85c471_common_init(const machine_t *model) { machine_at_common_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&sis_85c471_device); @@ -913,14 +914,14 @@ machine_at_pci400ca_init(const machine_t *model) pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_device); + device_add(&keyboard_at_ami_device); device_add(&sio_device); device_add(&intel_flash_bxt_ami_device); device_add(&i420tx_device); device_add(&ncr53c810_onboard_pci_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -956,7 +957,7 @@ machine_at_greenb_init(const machine_t *model) machine_at_common_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&contaq_82c597_device); @@ -979,7 +980,7 @@ machine_at_4gpv5_init(const machine_t *model) machine_at_common_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&contaq_82c596a_device); @@ -1351,7 +1352,7 @@ machine_at_486sp3_init(const machine_t *model) pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ + device_add(&keyboard_at_ami_device); /* Uses the AMIKEY KBC */ device_add(&sio_device); device_add(&fdc37c663_ide_device); device_add(&sst_flash_29ee010_device); @@ -1417,7 +1418,7 @@ machine_at_pci400cb_init(const machine_t *model) device_add(&ims8848_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -1446,7 +1447,7 @@ machine_at_g486ip_init(const machine_t *model) device_add(&ims8848_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -1506,7 +1507,7 @@ machine_at_486ap4_init(const machine_t *model) pci_register_slot(0x0c, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 0c = Slot 4 */ device_add(&keyboard_ps2_ami_pci_device); /* Uses the AMIKEY KBC */ - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&i420ex_device); @@ -1986,7 +1987,7 @@ machine_at_atc1415_init(const machine_t *model) device_add(&intel_flash_bxt_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -2247,7 +2248,7 @@ machine_at_ecsal486_init(const machine_t *model) device_add(&ali1429g_device); device_add(&keyboard_ps2_ami_pci_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -2290,9 +2291,100 @@ machine_at_atc1762_init(const machine_t *model) device_add(&ali1429g_device); device_add(&keyboard_ps2_ami_pci_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); + return ret; +} + +int +machine_at_dataexpert386wb_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/dataexpert386wb/st0386-wb-ver2-0-618f078c738cb397184464.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&opti391_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + +int +machine_at_genoa486_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/genoa486/AMI486.BIO", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + device_add(&compaq_genoa_device); + device_add(&port_92_key_device); + + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + +int +machine_at_ga486l_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/ga486l/ga-486l_bios.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&opti381_device); + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); + + return ret; +} + +int +machine_at_cougar_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/cougar/COUGRMRB.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_vlb_device); + + device_add(&opti499_device); + device_add(&fdc37c665_ide_pri_device); + + device_add(&keyboard_at_ami_device); + + if (fdc_current[0] == FDC_INTERNAL) + device_add(&fdc_at_device); return ret; } diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index a0b522371d..0b45fe60ca 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -112,7 +112,7 @@ machine_at_cmdpc_init(const machine_t *model) mem_remap_top(384); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); cmd_uart = device_add(&ns8250_device); diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 7f31d4ecd1..0ac541e909 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -779,7 +779,7 @@ machine_at_compaq_init(const machine_t *model, int type) { compaq_machine_type = type; - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); if (type < COMPAQ_PORTABLEIII386) { @@ -798,7 +798,7 @@ machine_at_compaq_init(const machine_t *model, int type) break; case COMPAQ_PORTABLEIII: - if (hdc_current == 1) + if (hdc_current[0] == HDC_INTERNAL) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); @@ -806,7 +806,7 @@ machine_at_compaq_init(const machine_t *model, int type) break; case COMPAQ_PORTABLEIII386: - if (hdc_current == 1) + if (hdc_current[0] == HDC_INTERNAL) device_add(&ide_isa_device); if (gfxcard[0] == VID_INTERNAL) device_add(&compaq_plasma_device); diff --git a/src/machine/m_at_slot1.c b/src/machine/m_at_slot1.c index d1486b5790..4159983643 100644 --- a/src/machine/m_at_slot1.c +++ b/src/machine/m_at_slot1.c @@ -408,11 +408,10 @@ machine_at_atc6310bxii_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); - pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x0E, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4); device_add(&i440bx_device); device_add(&slc90e66_device); @@ -530,8 +529,8 @@ machine_at_s1846_init(const machine_t *model) spd_register(SPD_TYPE_SDRAM, 0x7, 256); if (sound_card_current[0] == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); /* found on other Tyan boards around the same time */ + device_add(machine_get_snd_device(machine)); + device_add(&ct1297_device); /* no good pictures, but the marking looks like CT1297 from a distance */ } return ret; @@ -675,8 +674,8 @@ machine_at_gt694va_init(const machine_t *model) hwm_values.temperatures[2] = 0; /* unused */ if (sound_card_current[0] == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); /* assumed */ + device_add(machine_get_snd_device(machine)); + device_add(&cs4297_device); /* no good pictures, but the marking looks like CS4297 from a distance */ } return ret; @@ -739,7 +738,7 @@ machine_at_ms6168_common_init(const machine_t *model) spd_register(SPD_TYPE_SDRAM, 0x3, 256); if (sound_card_current[0] == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); + device_add(machine_get_snd_device(machine)); device_add(&cs4297_device); } } @@ -823,19 +822,21 @@ machine_at_p6f99_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1 | FLAG_TRC_CONTROLS_CPURST); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_SOUND, 2, 3, 4, 1); pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x0D, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0C, PCI_CARD_SOUND, 2, 3, 4, 1); pci_register_slot(0x02, PCI_CARD_AGPBRIDGE, 0, 0, 0, 0); device_add(&sis_5600_device); device_add(&keyboard_ps2_ami_pci_device); device_add(&it8661f_device); device_add(&winbond_flash_w29c020_device); - if (sound_card_current[0] == SOUND_INTERNAL) - device_add(&es1371_onboard_device); + if (sound_card_current[0] == SOUND_INTERNAL) { + device_add(machine_get_snd_device(machine)); + device_add(&ct1297_device); + } return ret; } diff --git a/src/machine/m_at_socket370.c b/src/machine/m_at_socket370.c index 9e686ae8bc..6d7b8c7100 100644 --- a/src/machine/m_at_socket370.c +++ b/src/machine/m_at_socket370.c @@ -100,13 +100,13 @@ machine_at_s1857_init(const machine_t *model) device_add(&i440bx_device); device_add(&piix4e_device); device_add(&keyboard_ps2_ami_pci_device); - device_add(&w83977ef_370_device); + device_add(&w83977ef_device); device_add(&intel_flash_bxt_device); spd_register(SPD_TYPE_SDRAM, 0x7, 256); if (sound_card_current[0] == SOUND_INTERNAL) { - device_add(&es1371_onboard_device); - device_add(&cs4297_device); /* found on other Tyan boards around the same time */ + device_add(machine_get_snd_device(machine)); + device_add(&cs4297_device); /* no good pictures, but the marking looks like CS4297 from a distance */ } return ret; diff --git a/src/machine/m_at_socket4.c b/src/machine/m_at_socket4.c index f7aad92ecd..79e46819e3 100644 --- a/src/machine/m_at_socket4.c +++ b/src/machine/m_at_socket4.c @@ -293,10 +293,10 @@ machine_at_award_common_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); - device_add(&keyboard_ps2_ami_pci_device); + device_add(&keyboard_at_ami_device); device_add(&sio_zb_device); device_add(&intel_flash_bxt_device); } @@ -402,7 +402,7 @@ machine_at_p5vl_init(const machine_t *model) device_add(&sst_flash_29ee010_device); device_add(&keyboard_at_ami_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; diff --git a/src/machine/m_at_socket5.c b/src/machine/m_at_socket5.c index ff59ec65fb..a5ab30c420 100644 --- a/src/machine/m_at_socket5.c +++ b/src/machine/m_at_socket5.c @@ -345,7 +345,8 @@ machine_at_pt2000_init(const machine_t *model) pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); - device_add(&keyboard_ps2_ami_pci_device); + /* Should be VIA, but we do not emulate that yet. */ + device_add(&keyboard_ps2_holtek_device); device_add(&i430fx_device); device_add(&piix_device); device_add(&pc87332_398_device); @@ -370,7 +371,7 @@ machine_at_pat54pv_init(const machine_t *model) device_add(&opti5x7_device); device_add(&keyboard_ps2_intel_ami_pci_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; @@ -400,7 +401,7 @@ machine_at_hot543_init(const machine_t *model) device_add(&sst_flash_29ee010_device); device_add(&keyboard_at_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); return ret; diff --git a/src/machine/m_at_socket7.c b/src/machine/m_at_socket7.c index 49ad043e8c..d7e2840a97 100644 --- a/src/machine/m_at_socket7.c +++ b/src/machine/m_at_socket7.c @@ -443,7 +443,8 @@ machine_at_epc2102_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_at_common_init(model); + machine_at_common_init_ex(model, 2); + device_add_params(&at_nvr_device, (void *) 0x20); pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); @@ -454,9 +455,9 @@ machine_at_epc2102_init(const machine_t *model) pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); - device_add(&keyboard_ps2_pci_device); + device_add(&keyboard_ps2_intel_ami_pci_device); device_add(&i82091aa_device); - device_add(&intel_flash_bxt_device); + device_add(&sst_flash_39sf010_device); return ret; } @@ -869,13 +870,17 @@ machine_at_nupro592_init(const machine_t *model) pci_init(PCI_CONFIG_TYPE_1); pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0B, PCI_CARD_VIDEO, 3, 4, 1, 2); /* C&T B69000 */ + pci_register_slot(0x0C, PCI_CARD_NETWORK, 4, 1, 2, 3); /* Intel 82559 */ pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x12, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x14, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); /*Strongly suspect these are on-board slots*/ - pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); /* PIIX4 */ + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + device_add(&i430tx_device); device_add(&piix4_device); device_add(&keyboard_ps2_ami_pci_device); @@ -930,7 +935,7 @@ machine_at_tx97_init(const machine_t *model) return ret; } -#if defined(DEV_BRANCH) && defined(USE_AN430TX) +#ifdef USE_AN430TX int machine_at_an430tx_init(const machine_t *model) { @@ -974,7 +979,7 @@ machine_at_an430tx_init(const machine_t *model) return ret; } -#endif +#endif /* USE_AN430TX */ int machine_at_ym430tx_init(const machine_t *model) diff --git a/src/machine/m_at_socket7_3v.c b/src/machine/m_at_socket7_3v.c index 380e56e410..c36fade865 100644 --- a/src/machine/m_at_socket7_3v.c +++ b/src/machine/m_at_socket7_3v.c @@ -816,7 +816,7 @@ machine_at_vectra54_init(const machine_t *model) device_add(&i430fx_device); device_add(&piix_device); - device_add(&fdc37c931apm_device); + device_add(&fdc37c932_device); device_add(&sst_flash_29ee010_device); return ret; diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 8262726fb1..eace59779e 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -33,6 +33,7 @@ #include <86box/timer.h> #include <86box/nvr.h> #include <86box/sio.h> +#include <86box/sound.h> #include <86box/hwm.h> #include <86box/spd.h> #include <86box/video.h> @@ -322,6 +323,12 @@ machine_at_ap440fx_init(const machine_t *model) device_add(&pc87307_device); device_add(&intel_flash_bxt_ami_device); + if (sound_card_current[0] == SOUND_INTERNAL) + device_add(machine_get_snd_device(machine)); + + if (gfxcard[0] == VID_INTERNAL) + device_add(machine_get_vid_device(machine)); + return ret; } diff --git a/src/machine/m_at_sockets7.c b/src/machine/m_at_sockets7.c index 32319e160d..0360b56502 100644 --- a/src/machine/m_at_sockets7.c +++ b/src/machine/m_at_sockets7.c @@ -135,6 +135,11 @@ machine_at_gwlucas_init(const machine_t *model) device_add(&sst_flash_39sf020_device); spd_register(SPD_TYPE_SDRAM, 0x7, 512); + if (sound_card_current[0] == SOUND_INTERNAL) { + device_add(machine_get_snd_device(machine)); + device_add(&cs4297_device); + } + return ret; } @@ -258,7 +263,7 @@ machine_at_mvp3_init(const machine_t *model) device_add(&via_mvp3_device); device_add(&via_vt82c586b_device); device_add(&keyboard_ps2_pci_device); - device_add(&w83877tf_device); + device_add(&w83877tf_acorp_device); device_add(&sst_flash_39sf010_device); spd_register(SPD_TYPE_SDRAM, 0x3, 256); diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index e3e24cf2c5..3c83b0ccec 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -815,7 +815,7 @@ machine_at_t3100e_init(const machine_t *model) device_add(&keyboard_at_toshiba_device); - if (fdc_type == FDC_INTERNAL) { + if (fdc_current[0] == FDC_INTERNAL) { device_add(&fdc_at_device); } @@ -850,6 +850,9 @@ machine_at_t3100e_init(const machine_t *model) NULL, MEM_MAPPING_INTERNAL, &t3100e_ems); mem_mapping_disable(&t3100e_ems.upper_mapping); + if (mem_size < (16384 - 448)) + mem_set_mem_state_both(mem_size * 1024, 384 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + device_add(&t3100e_device); return ret; diff --git a/src/machine/m_elt.c b/src/machine/m_elt.c index a69b621848..812755898b 100644 --- a/src/machine/m_elt.c +++ b/src/machine/m_elt.c @@ -178,7 +178,7 @@ machine_elt_init(const machine_t *model) pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); if (gfxcard[0] == VID_INTERNAL) { diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index e541cf7183..42034e2f66 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -660,7 +660,7 @@ europc_boot(UNUSED(const device_t *info)) * * We only do this if we have not configured another one. */ - if (hdc_current == 1) + if (hdc_current[0] == HDC_INTERNAL) (void) device_add(&xta_hd20_device); return sys; diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index 804da8e302..16020826de 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -96,6 +96,7 @@ typedef struct pcjr_t { int firstline; int lastline; int composite; + int apply_hd; /* Keyboard Controller stuff. */ int latched; @@ -107,6 +108,525 @@ typedef struct pcjr_t { pc_timer_t send_delay_timer; } pcjr_t; +/*PCjr keyboard has no escape scancodes, and no scancodes beyond 54 + Map right alt to 54h (FN) */ +const scancode scancode_pcjr[512] = { + // clang-format off + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 012 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0 }, .brk = { 0 } }, /* 054 */ + { .mk = { 0 }, .brk = { 0 } }, /* 055 */ + { .mk = { 0x55, 0 }, .brk = { 0xd5, 0 } }, /* 056 */ + { .mk = { 0 }, .brk = { 0 } }, /* 057 */ + { .mk = { 0 }, .brk = { 0 } }, /* 058 */ + { .mk = { 0 }, .brk = { 0 } }, /* 059 */ + { .mk = { 0 }, .brk = { 0 } }, /* 05a */ + { .mk = { 0 }, .brk = { 0 } }, /* 05b */ + { .mk = { 0 }, .brk = { 0 } }, /* 05c */ + { .mk = { 0 }, .brk = { 0 } }, /* 05d */ + { .mk = { 0 }, .brk = { 0 } }, /* 05e */ + { .mk = { 0 }, .brk = { 0 } }, /* 05f */ + { .mk = { 0 }, .brk = { 0 } }, /* 060 */ + { .mk = { 0 }, .brk = { 0 } }, /* 061 */ + { .mk = { 0 }, .brk = { 0 } }, /* 062 */ + { .mk = { 0 }, .brk = { 0 } }, /* 063 */ + { .mk = { 0 }, .brk = { 0 } }, /* 064 */ + { .mk = { 0 }, .brk = { 0 } }, /* 065 */ + { .mk = { 0 }, .brk = { 0 } }, /* 066 */ + { .mk = { 0 }, .brk = { 0 } }, /* 067 */ + { .mk = { 0 }, .brk = { 0 } }, /* 068 */ + { .mk = { 0 }, .brk = { 0 } }, /* 069 */ + { .mk = { 0 }, .brk = { 0 } }, /* 06a */ + { .mk = { 0 }, .brk = { 0 } }, /* 06b */ + { .mk = { 0 }, .brk = { 0 } }, /* 06c */ + { .mk = { 0 }, .brk = { 0 } }, /* 06d */ + { .mk = { 0 }, .brk = { 0 } }, /* 06e */ + { .mk = { 0 }, .brk = { 0 } }, /* 06f */ + { .mk = { 0 }, .brk = { 0 } }, /* 070 */ + { .mk = { 0 }, .brk = { 0 } }, /* 071 */ + { .mk = { 0 }, .brk = { 0 } }, /* 072 */ + { .mk = { 0 }, .brk = { 0 } }, /* 073 */ + { .mk = { 0 }, .brk = { 0 } }, /* 074 */ + { .mk = { 0 }, .brk = { 0 } }, /* 075 */ + { .mk = { 0 }, .brk = { 0 } }, /* 076 */ + { .mk = { 0 }, .brk = { 0 } }, /* 077 */ + { .mk = { 0 }, .brk = { 0 } }, /* 078 */ + { .mk = { 0 }, .brk = { 0 } }, /* 079 */ + { .mk = { 0 }, .brk = { 0 } }, /* 07a */ + { .mk = { 0 }, .brk = { 0 } }, /* 07b */ + { .mk = { 0 }, .brk = { 0 } }, /* 07c */ + { .mk = { 0 }, .brk = { 0 } }, /* 07d */ + { .mk = { 0 }, .brk = { 0 } }, /* 07e */ + { .mk = { 0 }, .brk = { 0 } }, /* 07f */ + { .mk = { 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = { 0 }, .brk = { 0 } }, /* 100 */ + { .mk = { 0 }, .brk = { 0 } }, /* 101 */ + { .mk = { 0 }, .brk = { 0 } }, /* 102 */ + { .mk = { 0 }, .brk = { 0 } }, /* 103 */ + { .mk = { 0 }, .brk = { 0 } }, /* 104 */ + { .mk = { 0 }, .brk = { 0 } }, /* 105 */ + { .mk = { 0 }, .brk = { 0 } }, /* 106 */ + { .mk = { 0 }, .brk = { 0 } }, /* 107 */ + { .mk = { 0 }, .brk = { 0 } }, /* 108 */ + { .mk = { 0 }, .brk = { 0 } }, /* 109 */ + { .mk = { 0 }, .brk = { 0 } }, /* 10a */ + { .mk = { 0 }, .brk = { 0 } }, /* 10b */ + { .mk = { 0 }, .brk = { 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = { 0 }, .brk = { 0 } }, /* 10e */ + { .mk = { 0 }, .brk = { 0 } }, /* 10f */ + { .mk = { 0 }, .brk = { 0 } }, /* 110 */ + { .mk = { 0 }, .brk = { 0 } }, /* 111 */ + { .mk = { 0 }, .brk = { 0 } }, /* 112 */ + { .mk = { 0 }, .brk = { 0 } }, /* 113 */ + { .mk = { 0 }, .brk = { 0 } }, /* 114 */ + { .mk = { 0 }, .brk = { 0 } }, /* 115 */ + { .mk = { 0 }, .brk = { 0 } }, /* 116 */ + { .mk = { 0 }, .brk = { 0 } }, /* 117 */ + { .mk = { 0 }, .brk = { 0 } }, /* 118 */ + { .mk = { 0 }, .brk = { 0 } }, /* 119 */ + { .mk = { 0 }, .brk = { 0 } }, /* 11a */ + { .mk = { 0 }, .brk = { 0 } }, /* 11b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 11c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 11d */ + { .mk = { 0 }, .brk = { 0 } }, /* 11e */ + { .mk = { 0 }, .brk = { 0 } }, /* 11f */ + { .mk = { 0 }, .brk = { 0 } }, /* 120 */ + { .mk = { 0 }, .brk = { 0 } }, /* 121 */ + { .mk = { 0 }, .brk = { 0 } }, /* 122 */ + { .mk = { 0 }, .brk = { 0 } }, /* 123 */ + { .mk = { 0 }, .brk = { 0 } }, /* 124 */ + { .mk = { 0 }, .brk = { 0 } }, /* 125 */ + { .mk = { 0 }, .brk = { 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = { 0 }, .brk = { 0 } }, /* 12c */ + { .mk = { 0 }, .brk = { 0 } }, /* 12d */ + { .mk = { 0 }, .brk = { 0 } }, /* 12e */ + { .mk = { 0 }, .brk = { 0 } }, /* 12f */ + { .mk = { 0 }, .brk = { 0 } }, /* 130 */ + { .mk = { 0 }, .brk = { 0 } }, /* 131 */ + { .mk = { 0 }, .brk = { 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = { 0 }, .brk = { 0 } }, /* 134 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 137 */ + { .mk = { 0x54, 0 }, .brk = { 0xd4, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = { 0 }, .brk = { 0 } }, /* 13a */ + { .mk = { 0 }, .brk = { 0 } }, /* 13b */ + { .mk = { 0 }, .brk = { 0 } }, /* 13c */ + { .mk = { 0 }, .brk = { 0 } }, /* 13d */ + { .mk = { 0 }, .brk = { 0 } }, /* 13e */ + { .mk = { 0 }, .brk = { 0 } }, /* 13f */ + { .mk = { 0 }, .brk = { 0 } }, /* 140 */ + { .mk = { 0 }, .brk = { 0 } }, /* 141 */ + { .mk = { 0 }, .brk = { 0 } }, /* 142 */ + { .mk = { 0 }, .brk = { 0 } }, /* 143 */ + { .mk = { 0 }, .brk = { 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 146 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 147 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 148 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 14b */ + { .mk = { 0 }, .brk = { 0 } }, /* 14c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 14d */ + { .mk = { 0 }, .brk = { 0 } }, /* 14e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 14f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 150 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 151 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 152 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = { 0 }, .brk = { 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = { 0 }, .brk = { 0 } }, /* 157 */ + { .mk = { 0 }, .brk = { 0 } }, /* 158 */ + { .mk = { 0 }, .brk = { 0 } }, /* 159 */ + { .mk = { 0 }, .brk = { 0 } }, /* 15a */ + { .mk = { 0 }, .brk = { 0 } }, /* 15b */ + { .mk = { 0 }, .brk = { 0 } }, /* 15c */ + { .mk = { 0 }, .brk = { 0 } }, /* 15d */ + { .mk = { 0 }, .brk = { 0 } }, /* 15e */ + { .mk = { 0 }, .brk = { 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = { 0 }, .brk = { 0 } }, /* 161 */ + { .mk = { 0 }, .brk = { 0 } }, /* 162 */ + { .mk = { 0 }, .brk = { 0 } }, /* 163 */ + { .mk = { 0 }, .brk = { 0 } }, /* 164 */ + { .mk = { 0 }, .brk = { 0 } }, /* 165 */ + { .mk = { 0 }, .brk = { 0 } }, /* 166 */ + { .mk = { 0 }, .brk = { 0 } }, /* 167 */ + { .mk = { 0 }, .brk = { 0 } }, /* 168 */ + { .mk = { 0 }, .brk = { 0 } }, /* 169 */ + { .mk = { 0 }, .brk = { 0 } }, /* 16a */ + { .mk = { 0 }, .brk = { 0 } }, /* 16b */ + { .mk = { 0 }, .brk = { 0 } }, /* 16c */ + { .mk = { 0 }, .brk = { 0 } }, /* 16d */ + { .mk = { 0 }, .brk = { 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = { 0 }, .brk = { 0 } }, /* 170 */ + { .mk = { 0 }, .brk = { 0 } }, /* 171 */ + { .mk = { 0 }, .brk = { 0 } }, /* 172 */ + { .mk = { 0 }, .brk = { 0 } }, /* 173 */ + { .mk = { 0 }, .brk = { 0 } }, /* 174 */ + { .mk = { 0 }, .brk = { 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = { 0 }, .brk = { 0 } }, /* 177 */ + { .mk = { 0 }, .brk = { 0 } }, /* 178 */ + { .mk = { 0 }, .brk = { 0 } }, /* 179 */ + { .mk = { 0 }, .brk = { 0 } }, /* 17a */ + { .mk = { 0 }, .brk = { 0 } }, /* 17b */ + { .mk = { 0 }, .brk = { 0 } }, /* 17c */ + { .mk = { 0 }, .brk = { 0 } }, /* 17d */ + { .mk = { 0 }, .brk = { 0 } }, /* 17e */ + { .mk = { 0 }, .brk = { 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = { 0 }, .brk = { 0 } } /* 1ff */ + // clang-format on +}; + static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No additional waitstates*/ static uint8_t crtcmask[32] = { @@ -161,6 +681,19 @@ recalc_timings(pcjr_t *pcjr) pcjr->dispofftime = (uint64_t) (_dispofftime); } +static int +vid_get_h_overscan_size(pcjr_t *pcjr) +{ + int ret; + + if (pcjr->array[0] & 1) + ret = 128; + else + ret = 256; + + return ret; +} + static void vid_out(uint16_t addr, uint8_t val, void *priv) { @@ -181,6 +714,8 @@ vid_out(uint16_t addr, uint8_t val, void *priv) case 0x3d7: old = pcjr->crtc[pcjr->crtcreg]; pcjr->crtc[pcjr->crtcreg] = val & crtcmask[pcjr->crtcreg]; + if (pcjr->crtcreg == 2) + overscan_x = vid_get_h_overscan_size(pcjr); if (old != val) { if (pcjr->crtcreg < 0xe || pcjr->crtcreg > 0x10) { pcjr->fullchange = changeframecount; @@ -273,6 +808,85 @@ vid_read(uint32_t addr, void *priv) return (pcjr->b8000[addr & 0x3fff]); } +static int +vid_get_h_overscan_delta(pcjr_t *pcjr) +{ + int def; + int coef; + int ret; + + switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { + case 0x13: /*320x200x16*/ + def = 0x56; + coef = 8; + break; + case 0x12: /*160x200x16*/ + def = 0x2c; /* I'm going to assume a datasheet erratum here. */ + coef = 16; + break; + case 0x03: /*640x200x4*/ + def = 0x56; + coef = 8; + break; + case 0x01: /*80 column text*/ + def = 0x5a; + coef = 8; + break; + case 0x00: /*40 column text*/ + default: + def = 0x2c; + coef = 16; + break; + case 0x02: /*320x200x4*/ + def = 0x2b; + coef = 16; + break; + case 0x102: /*640x200x2*/ + def = 0x2b; + coef = 16; + break; + } + + ret = pcjr->crtc[0x02] - def; + + if (ret < -8) + ret = -8; + + if (ret > 8) + ret = 8; + + return ret * coef; +} + +static void +vid_blit_h_overscan(pcjr_t *pcjr) +{ + int cols = (pcjr->array[2] & 0xf) + 16;; + int y0 = pcjr->firstline << 1; + int y = (pcjr->lastline << 1) + 16; + int ho_s = vid_get_h_overscan_size(pcjr); + int i; + int x; + + if (pcjr->array[0] & 1) + x = (pcjr->crtc[1] << 3) + ho_s; + else + x = (pcjr->crtc[1] << 4) + ho_s; + + for (i = 0; i < 16; i++) { + hline(buffer32, 0, y0 + i, x, cols); + hline(buffer32, 0, y + i, x, cols); + + if (pcjr->composite) { + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y0 + i]); + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[y + i]); + } else { + video_process_8(x, y0 + i); + video_process_8(x, y + i); + } + } +} + static void vid_poll(void *priv) { @@ -288,6 +902,9 @@ vid_poll(void *priv) uint16_t dat; int cols[4]; int oldsc; + int l = (pcjr->displine << 1) + 16; + int ho_s = vid_get_h_overscan_size(pcjr); + int ho_d = vid_get_h_overscan_delta(pcjr) + (ho_s / 2); if (!pcjr->linepos) { timer_advance_u64(&pcjr->timer, pcjr->dispofftime); @@ -306,13 +923,13 @@ vid_poll(void *priv) } pcjr->lastline = pcjr->displine; cols[0] = (pcjr->array[2] & 0xf) + 16; - for (uint8_t c = 0; c < 8; c++) { - (buffer32->line[pcjr->displine])[c] = cols[0]; - if (pcjr->array[0] & 1) { - buffer32->line[pcjr->displine << 1][c + (pcjr->crtc[1] << 3) + 8] = buffer32->line[(pcjr->displine << 1) + 1][c + (pcjr->crtc[1] << 3) + 8] = cols[0]; - } else { - buffer32->line[pcjr->displine << 1][c + (pcjr->crtc[1] << 4) + 8] = buffer32->line[(pcjr->displine << 1) + 1][c + (pcjr->crtc[1] << 4) + 8] = cols[0]; - } + + if (pcjr->array[0] & 1) { + hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + } else { + hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]); } switch (pcjr->addr_mode) { @@ -326,105 +943,139 @@ vid_poll(void *priv) case 3: /*High resolution graphics*/ offset = (pcjr->sc & 3) * 0x2000; break; - default: break; } switch ((pcjr->array[0] & 0x13) | ((pcjr->array[3] & 0x08) << 5)) { case 0x13: /*320x200x16*/ for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + int ef_x = (x << 3) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; pcjr->ma++; - buffer32->line[pcjr->displine << 1][(x << 3) + 8] = buffer32->line[pcjr->displine << 1][(x << 3) + 9] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 9] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; - buffer32->line[pcjr->displine << 1][(x << 3) + 10] = buffer32->line[pcjr->displine << 1][(x << 3) + 11] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 10] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 11] = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; - buffer32->line[pcjr->displine << 1][(x << 3) + 12] = buffer32->line[pcjr->displine << 1][(x << 3) + 13] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 12] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 13] = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; - buffer32->line[pcjr->displine << 1][(x << 3) + 14] = buffer32->line[pcjr->displine << 1][(x << 3) + 15] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 14] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 15] = pcjr->array[(dat & pcjr->array[1]) + 16] + 16; + buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = + buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = + pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = + buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = + pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] = + buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] = + pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] = + buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] = + pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16; } break; case 0x12: /*160x200x16*/ for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + int ef_x = (x << 4) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; pcjr->ma++; - buffer32->line[pcjr->displine << 1][(x << 4) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + 9] = buffer32->line[pcjr->displine << 1][(x << 4) + 10] = buffer32->line[pcjr->displine << 1][(x << 4) + 11] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 9] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 10] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 11] = pcjr->array[((dat >> 12) & pcjr->array[1]) + 16] + 16; - buffer32->line[pcjr->displine << 1][(x << 4) + 12] = buffer32->line[pcjr->displine << 1][(x << 4) + 13] = buffer32->line[pcjr->displine << 1][(x << 4) + 14] = buffer32->line[pcjr->displine << 1][(x << 4) + 15] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 12] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 13] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 14] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 15] = pcjr->array[((dat >> 8) & pcjr->array[1]) + 16] + 16; - buffer32->line[pcjr->displine << 1][(x << 4) + 16] = buffer32->line[pcjr->displine << 1][(x << 4) + 17] = buffer32->line[pcjr->displine << 1][(x << 4) + 18] = buffer32->line[pcjr->displine << 1][(x << 4) + 19] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 16] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 17] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 18] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 19] = pcjr->array[((dat >> 4) & pcjr->array[1]) + 16] + 16; - buffer32->line[pcjr->displine << 1][(x << 4) + 20] = buffer32->line[pcjr->displine << 1][(x << 4) + 21] = buffer32->line[pcjr->displine << 1][(x << 4) + 22] = buffer32->line[pcjr->displine << 1][(x << 4) + 23] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 20] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 21] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 22] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + 23] = pcjr->array[(dat & pcjr->array[1]) + 16] + 16; + buffer32->line[l][ef_x] = buffer32->line[l][ef_x + 1] = + buffer32->line[l][ef_x + 2] = buffer32->line[l][ef_x + 3] = + buffer32->line[l + 1][ef_x] = buffer32->line[l + 1][ef_x + 1] = + buffer32->line[l + 1][ef_x + 2] = buffer32->line[l + 1][ef_x + 3] = + pcjr->array[((dat >> 12) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 4] = buffer32->line[l][ef_x + 5] = + buffer32->line[l][ef_x + 6] = buffer32->line[l][ef_x + 7] = + buffer32->line[l + 1][ef_x + 4] = buffer32->line[l + 1][ef_x + 5] = + buffer32->line[l + 1][ef_x + 6] = buffer32->line[l + 1][ef_x + 7] = + pcjr->array[((dat >> 8) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 8] = buffer32->line[l][ef_x + 9] = + buffer32->line[l][ef_x + 10] = buffer32->line[l][ef_x + 11] = + buffer32->line[l + 1][ef_x + 8] = buffer32->line[l + 1][ef_x + 9] = + buffer32->line[l + 1][ef_x + 10] = buffer32->line[l + 1][ef_x + 11] = + pcjr->array[((dat >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; + buffer32->line[l][ef_x + 12] = buffer32->line[l][ef_x + 13] = + buffer32->line[l][ef_x + 14] = buffer32->line[l][ef_x + 15] = + buffer32->line[l + 1][ef_x + 12] = buffer32->line[l + 1][ef_x + 13] = + buffer32->line[l + 1][ef_x + 14] = buffer32->line[l + 1][ef_x + 15] = + pcjr->array[(dat & pcjr->array[1] & 0x0f) + 16] + 16; } break; case 0x03: /*640x200x4*/ for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + int ef_x = (x << 3) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset]; pcjr->ma++; for (uint8_t c = 0; c < 8; c++) { chr = (dat >> 7) & 1; chr |= ((dat >> 14) & 2); - buffer32->line[pcjr->displine << 1][(x << 3) + 8 + c] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + 8 + c] = pcjr->array[(chr & pcjr->array[1]) + 16] + 16; + buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = + pcjr->array[(chr & pcjr->array[1] & 0x0f) + 16] + 16; dat <<= 1; } } break; case 0x01: /*80 column text*/ for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 3) + ho_d; chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) cols[1] = cols[0]; } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; - } - if (pcjr->sc & 8) { - for (uint8_t c = 0; c < 8; c++) { - buffer32->line[pcjr->displine << 1][(x << 3) + c + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] = cols[0]; - } - } else { - for (uint8_t c = 0; c < 8; c++) { - buffer32->line[pcjr->displine << 1][(x << 3) + c + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; } - if (drawcursor) { + if (pcjr->sc & 8) + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + c] = + buffer32->line[l + 1][ef_x + c] = cols[0]; + else + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + c] = + buffer32->line[l + 1][ef_x + c] = + cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + if (drawcursor) for (uint8_t c = 0; c < 8; c++) { - buffer32->line[pcjr->displine << 1][(x << 3) + c + 8] ^= 15; - buffer32->line[(pcjr->displine << 1) + 1][(x << 3) + c + 8] ^= 15; + buffer32->line[l][ef_x + c] ^= 15; + buffer32->line[l + 1][ef_x + c] ^= 15; } - } pcjr->ma++; } break; case 0x00: /*40 column text*/ for (x = 0; x < pcjr->crtc[1]; x++) { + int ef_x = (x << 4) + ho_d; chr = pcjr->vram[((pcjr->ma << 1) & mask) + offset]; attr = pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; drawcursor = ((pcjr->ma == ca) && pcjr->con && pcjr->cursoron); if (pcjr->array[3] & 4) { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1]) + 16] + 16; + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[(((attr >> 4) & 7) & pcjr->array[1] & 0x0f) + 16] + 16; if ((pcjr->blink & 16) && (attr & 0x80) && !drawcursor) cols[1] = cols[0]; } else { - cols[1] = pcjr->array[((attr & 15) & pcjr->array[1]) + 16] + 16; - cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1]) + 16] + 16; + cols[1] = pcjr->array[((attr & 15) & pcjr->array[1] & 0x0f) + 16] + 16; + cols[0] = pcjr->array[((attr >> 4) & pcjr->array[1] & 0x0f) + 16] + 16; } pcjr->ma++; - if (pcjr->sc & 8) { - for (uint8_t c = 0; c < 8; c++) { - buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[0]; - } - } else { - for (uint8_t c = 0; c < 8; c++) { - buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - if (drawcursor) { + if (pcjr->sc & 8) + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + (c << 1)] = + buffer32->line[l][ef_x + (c << 1) + 1] = + buffer32->line[l + 1][ef_x + (c << 1)] = + buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[0]; + else + for (uint8_t c = 0; c < 8; c++) + buffer32->line[l][ef_x + (c << 1)] = + buffer32->line[l][ef_x + (c << 1) + 1] = + buffer32->line[l + 1][ef_x + (c << 1)] = + buffer32->line[l + 1][ef_x + (c << 1) + 1] = + cols[(fontdat[chr][pcjr->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; + if (drawcursor) for (uint8_t c = 0; c < 16; c++) { - buffer32->line[pcjr->displine << 1][(x << 4) + c + 8] ^= 15; - buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + c + 8] ^= 15; + buffer32->line[l][ef_x + c] ^= 15; + buffer32->line[l + 1][ef_x + c] ^= 15; } - } } break; case 0x02: /*320x200x4*/ @@ -433,10 +1084,15 @@ vid_poll(void *priv) cols[2] = pcjr->array[2 + 16] + 16; cols[3] = pcjr->array[3 + 16] + 16; for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + int ef_x = (x << 4) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; pcjr->ma++; for (uint8_t c = 0; c < 8; c++) { - buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 8] = buffer32->line[pcjr->displine << 1][(x << 4) + (c << 1) + 1 + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; + buffer32->line[l][ef_x + (c << 1)] = + buffer32->line[l][ef_x + (c << 1) + 1] = + buffer32->line[l + 1][ef_x + (c << 1)] = + buffer32->line[l + 1][ef_x + (c << 1) + 1] = cols[dat >> 14]; dat <<= 2; } } @@ -445,10 +1101,13 @@ vid_poll(void *priv) cols[0] = pcjr->array[0 + 16] + 16; cols[1] = pcjr->array[1 + 16] + 16; for (x = 0; x < pcjr->crtc[1]; x++) { - dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; + int ef_x = (x << 4) + ho_d; + dat = (pcjr->vram[((pcjr->ma << 1) & mask) + offset] << 8) | + pcjr->vram[((pcjr->ma << 1) & mask) + offset + 1]; pcjr->ma++; for (uint8_t c = 0; c < 16; c++) { - buffer32->line[pcjr->displine << 1][(x << 4) + c + 8] = buffer32->line[(pcjr->displine << 1) + 1][(x << 4) + c + 8] = cols[dat >> 15]; + buffer32->line[l][ef_x + c] = buffer32->line[l + 1][ef_x + c] = + cols[dat >> 15]; dat <<= 1; } } @@ -460,33 +1119,33 @@ vid_poll(void *priv) } else { if (pcjr->array[3] & 4) { if (pcjr->array[0] & 1) { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 3) + 16, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, (pcjr->array[2] & 0xf) + 16); } else { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 4) + 16, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, (pcjr->array[2] & 0xf) + 16); } } else { cols[0] = pcjr->array[0 + 16] + 16; if (pcjr->array[0] & 1) { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 3) + 16, cols[0]); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 3) + 16, cols[0]); + hline(buffer32, 0, l, (pcjr->crtc[1] << 3) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 3) + ho_s, cols[0]); } else { - hline(buffer32, 0, (pcjr->displine << 1), (pcjr->crtc[1] << 4) + 16, cols[0]); - hline(buffer32, 0, (pcjr->displine << 1) + 1, (pcjr->crtc[1] << 4) + 16, cols[0]); + hline(buffer32, 0, l, (pcjr->crtc[1] << 4) + ho_s, cols[0]); + hline(buffer32, 0, l + 1, (pcjr->crtc[1] << 4) + ho_s, cols[0]); } } } if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + 16; + x = (pcjr->crtc[1] << 3) + ho_s; else - x = (pcjr->crtc[1] << 4) + 16; + x = (pcjr->crtc[1] << 4) + ho_s; if (pcjr->composite) { - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[pcjr->displine << 1]); - Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[(pcjr->displine << 1) + 1]); + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l]); + Composite_Process(pcjr->array[0], 0, x >> 2, buffer32->line[l + 1]); } else { - video_process_8(x, pcjr->displine << 1); - video_process_8(x, (pcjr->displine << 1) + 1); + video_process_8(x, l); + video_process_8(x, l + 1); } pcjr->sc = oldsc; if (pcjr->vc == pcjr->crtc[7] && !pcjr->sc) { @@ -547,37 +1206,45 @@ vid_poll(void *priv) picint(1 << 5); if (pcjr->crtc[7]) { if (pcjr->array[0] & 1) - x = (pcjr->crtc[1] << 3) + 16; + x = (pcjr->crtc[1] << 3) + ho_s; else - x = (pcjr->crtc[1] << 4) + 16; + x = (pcjr->crtc[1] << 4) + ho_s; pcjr->lastline++; xs_temp = x; ys_temp = (pcjr->lastline - pcjr->firstline) << 1; if ((xs_temp > 0) && (ys_temp > 0)) { + int actual_ys = ys_temp; + if (xs_temp < 64) xs_temp = 656; if (ys_temp < 32) ys_temp = 400; if (!enable_overscan) - xs_temp -= 16; + xs_temp -= ho_s; if ((xs_temp != xsize) || (ys_temp != ysize) || video_force_resize_get()) { xsize = xs_temp; ysize = ys_temp; - set_screen_size(xsize, ysize + (enable_overscan ? 16 : 0)); + + set_screen_size(xsize, ysize + (enable_overscan ? 32 : 0)); if (video_force_resize_get()) video_force_resize_set(0); } + vid_blit_h_overscan(pcjr); + if (enable_overscan) { - video_blit_memtoscreen(0, (pcjr->firstline - 4) << 1, - xsize, ((pcjr->lastline - pcjr->firstline) + 8) << 1); + video_blit_memtoscreen(0, pcjr->firstline << 1, + xsize, actual_ys + 32); + } else if (pcjr->apply_hd) { + video_blit_memtoscreen(ho_s / 2, (pcjr->firstline << 1) + 16, + xsize, actual_ys); } else { - video_blit_memtoscreen(8, pcjr->firstline << 1, - xsize, (pcjr->lastline - pcjr->firstline) << 1); + video_blit_memtoscreen(ho_d, (pcjr->firstline << 1) + 16, + xsize, actual_ys); } } @@ -771,6 +1438,34 @@ speed_changed(void *priv) recalc_timings(pcjr); } +static void +pcjr_vid_init(pcjr_t *pcjr) +{ + int display_type; + + video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); + + pcjr->memctrl = -1; + if (mem_size < 128) + pcjr->memctrl &= ~0x24; + + display_type = device_get_config_int("display_type"); + pcjr->composite = (display_type != PCJR_RGB); + pcjr->apply_hd = device_get_config_int("apply_hd"); + overscan_x = 256; + overscan_y = 32; + + mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, + vid_read, NULL, NULL, + vid_write, NULL, NULL, NULL, 0, pcjr); + io_sethandler(0x03d0, 16, + vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); + timer_add(&pcjr->timer, vid_poll, pcjr, 1); + + cga_palette = 0; + cgapal_rebuild(); +} + void pit_irq0_timer_pcjr(int new_out, int old_out, UNUSED(void *priv)) { @@ -799,6 +1494,13 @@ static const device_config_t pcjr_config[] = { { .description = "" } } }, + { + .name = "apply_hd", + .description = "Apply overscan deltas", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, { .name = "", .description = "", .type = CONFIG_END } // clang-format on }; @@ -820,7 +1522,6 @@ const device_t pcjr_device = { int machine_pcjr_init(UNUSED(const machine_t *model)) { - int display_type; pcjr_t *pcjr; int ret; @@ -833,11 +1534,6 @@ machine_pcjr_init(UNUSED(const machine_t *model)) pcjr = malloc(sizeof(pcjr_t)); memset(pcjr, 0x00, sizeof(pcjr_t)); - pcjr->memctrl = -1; - if (mem_size < 128) - pcjr->memctrl &= ~0x24; - display_type = machine_get_config_int("display_type"); - pcjr->composite = (display_type != PCJR_RGB); pic_init_pcjr(); pit_common_init(0, pit_irq0_timer_pcjr, NULL); @@ -847,16 +1543,10 @@ machine_pcjr_init(UNUSED(const machine_t *model)) /* Initialize the video controller. */ video_reset(gfxcard[0]); loadfont("roms/video/mda/mda.rom", 0); - mem_mapping_add(&pcjr->mapping, 0xb8000, 0x08000, - vid_read, NULL, NULL, - vid_write, NULL, NULL, NULL, 0, pcjr); - io_sethandler(0x03d0, 16, - vid_in, NULL, NULL, vid_out, NULL, NULL, pcjr); - timer_add(&pcjr->timer, vid_poll, pcjr, 1); - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); + device_context(&pcjr_device); + pcjr_vid_init(pcjr); + device_context_restore(); device_add_ex(&pcjr_device, pcjr); - cga_palette = 0; - cgapal_rebuild(); /* Initialize the keyboard. */ keyboard_scan = 1; @@ -866,7 +1556,7 @@ machine_pcjr_init(UNUSED(const machine_t *model)) io_sethandler(0x00a0, 8, kbd_read, NULL, NULL, kbd_write, NULL, NULL, pcjr); timer_add(&pcjr->send_delay_timer, kbd_poll, pcjr, 1); - keyboard_set_table(scancode_xt); + keyboard_set_table(scancode_pcjr); keyboard_send = kbd_adddata_ex; /* Technically it's the SN76496N, but the SN76489 is identical to the SN76496N. */ diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 34691773f5..a6a16d65ca 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -353,7 +353,7 @@ ps1_setup(int model) device_add(&fdc_at_ps1_device); /* Enable the builtin HDC. */ - if (hdc_current == 1) { + if (hdc_current[0] == HDC_INTERNAL) { priv = device_add(&ps1_hdc_device); ps1_hdc_inform(priv, &ps->ps1_91); diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index fa9c5acc2e..2887cca206 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -179,7 +179,7 @@ ps2_isa_setup(int model, int cpu_type) device_add(&fdc_at_ps1_device); /* Enable the builtin HDC. */ - if (hdc_current == 1) { + if (hdc_current[0] == HDC_INTERNAL) { priv = device_add(&ps1_hdc_device); ps1_hdc_inform(priv, &ps2->ps2_91); } diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 8ad69e314e..cb83d9be71 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -1395,7 +1395,7 @@ machine_ps2_common_init(const machine_t *model) { machine_common_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); dma16_init(); diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 1d4c3303f6..11bd41a664 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -27,6 +27,7 @@ #include <86box/86box.h> #include <86box/timer.h> #include <86box/io.h> +#include <86box/pic.h> #include <86box/pit.h> #include <86box/nmi.h> #include <86box/mem.h> @@ -52,6 +53,7 @@ enum { enum { TYPE_TANDY = 0, + TYPE_TANDY1000SX, TYPE_TANDY1000HX, TYPE_TANDY1000SL2 }; @@ -82,6 +84,7 @@ typedef struct t1kvid_t { uint32_t b8000_mask; uint32_t b8000_limit; uint8_t planar_ctrl; + uint8_t lp_strobe; int linepos; int displine; @@ -129,6 +132,7 @@ typedef struct tandy_t { uint32_t base; uint32_t mask; + int is_hx; int is_sl2; t1kvid_t *vid; @@ -138,262 +142,518 @@ static video_timings_t timing_dram = { VIDEO_BUS, 0, 0, 0, 0, 0, 0 }; /*No addit static const scancode scancode_tandy[512] = { // clang-format off - { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, - { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, - { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, - { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, - { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, - { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, - { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, - { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, - { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, - { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, - { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, - { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, - { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, - { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, - { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, - { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, - { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, - { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, - { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, - { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, - { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, - { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, - { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, - { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, - { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, - { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, - { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, - { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, - { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, - { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, - { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, - { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, - { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, - { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, - { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x56, 0}, {0xd6, 0} }, - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*054*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*058*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*05c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*060*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*064*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*068*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*06c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*070*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*074*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*078*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*07c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*080*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*084*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*088*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*08c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*090*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*094*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*098*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*09c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0fc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*100*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*104*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*108*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*10c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*110*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*114*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*118*/ - { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*11c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*120*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*124*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*128*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*12c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*130*/ - { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, - { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ - { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*138*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*13c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*140*/ - { {0}, {0} }, { {0}, {0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ - { {0x29, 0}, {0xa9, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0}, {0} }, { {0x2b, 0}, {0xab, 0} }, /*148*/ - { {0}, {0} }, { {0x4e, 0}, {0xce, 0} }, - { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ - { {0x4a, 0}, {0xca, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*154*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*158*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*15c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*160*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*164*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*168*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*16c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*170*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*174*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*148*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*17c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*180*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*184*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*188*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*18c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*190*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*194*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*198*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*19c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 013 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x56, 0 }, .brk = { 0xd6, 0 } }, /* 053 */ + { .mk = { 0 }, .brk = { 0 } }, /* 054 */ + { .mk = { 0 }, .brk = { 0 } }, /* 055 */ + { .mk = { 0 }, .brk = { 0 } }, /* 056 */ + { .mk = { 0 }, .brk = { 0 } }, /* 057 */ + { .mk = { 0 }, .brk = { 0 } }, /* 058 */ + { .mk = { 0 }, .brk = { 0 } }, /* 059 */ + { .mk = { 0 }, .brk = { 0 } }, /* 05a */ + { .mk = { 0 }, .brk = { 0 } }, /* 05b */ + { .mk = { 0 }, .brk = { 0 } }, /* 05c */ + { .mk = { 0 }, .brk = { 0 } }, /* 05d */ + { .mk = { 0 }, .brk = { 0 } }, /* 05e */ + { .mk = { 0 }, .brk = { 0 } }, /* 05f */ + { .mk = { 0 }, .brk = { 0 } }, /* 060 */ + { .mk = { 0 }, .brk = { 0 } }, /* 061 */ + { .mk = { 0 }, .brk = { 0 } }, /* 062 */ + { .mk = { 0 }, .brk = { 0 } }, /* 063 */ + { .mk = { 0 }, .brk = { 0 } }, /* 064 */ + { .mk = { 0 }, .brk = { 0 } }, /* 065 */ + { .mk = { 0 }, .brk = { 0 } }, /* 066 */ + { .mk = { 0 }, .brk = { 0 } }, /* 067 */ + { .mk = { 0 }, .brk = { 0 } }, /* 068 */ + { .mk = { 0 }, .brk = { 0 } }, /* 069 */ + { .mk = { 0 }, .brk = { 0 } }, /* 06a */ + { .mk = { 0 }, .brk = { 0 } }, /* 06b */ + { .mk = { 0 }, .brk = { 0 } }, /* 06c */ + { .mk = { 0 }, .brk = { 0 } }, /* 06d */ + { .mk = { 0 }, .brk = { 0 } }, /* 06e */ + { .mk = { 0 }, .brk = { 0 } }, /* 06f */ + { .mk = { 0 }, .brk = { 0 } }, /* 070 */ + { .mk = { 0 }, .brk = { 0 } }, /* 071 */ + { .mk = { 0 }, .brk = { 0 } }, /* 072 */ + { .mk = { 0 }, .brk = { 0 } }, /* 073 */ + { .mk = { 0 }, .brk = { 0 } }, /* 074 */ + { .mk = { 0 }, .brk = { 0 } }, /* 075 */ + { .mk = { 0 }, .brk = { 0 } }, /* 076 */ + { .mk = { 0 }, .brk = { 0 } }, /* 077 */ + { .mk = { 0 }, .brk = { 0 } }, /* 078 */ + { .mk = { 0 }, .brk = { 0 } }, /* 079 */ + { .mk = { 0 }, .brk = { 0 } }, /* 07a */ + { .mk = { 0 }, .brk = { 0 } }, /* 07b */ + { .mk = { 0 }, .brk = { 0 } }, /* 07c */ + { .mk = { 0 }, .brk = { 0 } }, /* 07d */ + { .mk = { 0 }, .brk = { 0 } }, /* 07e */ + { .mk = { 0 }, .brk = { 0 } }, /* 07f */ + { .mk = { 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = { 0 }, .brk = { 0 } }, /* 100 */ + { .mk = { 0 }, .brk = { 0 } }, /* 101 */ + { .mk = { 0 }, .brk = { 0 } }, /* 102 */ + { .mk = { 0 }, .brk = { 0 } }, /* 103 */ + { .mk = { 0 }, .brk = { 0 } }, /* 104 */ + { .mk = { 0 }, .brk = { 0 } }, /* 105 */ + { .mk = { 0 }, .brk = { 0 } }, /* 106 */ + { .mk = { 0 }, .brk = { 0 } }, /* 107 */ + { .mk = { 0 }, .brk = { 0 } }, /* 108 */ + { .mk = { 0 }, .brk = { 0 } }, /* 109 */ + { .mk = { 0 }, .brk = { 0 } }, /* 10a */ + { .mk = { 0 }, .brk = { 0 } }, /* 10b */ + { .mk = { 0 }, .brk = { 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = { 0 }, .brk = { 0 } }, /* 10e */ + { .mk = { 0 }, .brk = { 0 } }, /* 10f */ + { .mk = { 0 }, .brk = { 0 } }, /* 110 */ + { .mk = { 0 }, .brk = { 0 } }, /* 111 */ + { .mk = { 0 }, .brk = { 0 } }, /* 112 */ + { .mk = { 0 }, .brk = { 0 } }, /* 113 */ + { .mk = { 0 }, .brk = { 0 } }, /* 114 */ + { .mk = { 0 }, .brk = { 0 } }, /* 115 */ + { .mk = { 0 }, .brk = { 0 } }, /* 116 */ + { .mk = { 0 }, .brk = { 0 } }, /* 117 */ + { .mk = { 0 }, .brk = { 0 } }, /* 118 */ + { .mk = { 0 }, .brk = { 0 } }, /* 119 */ + { .mk = { 0 }, .brk = { 0 } }, /* 11a */ + { .mk = { 0 }, .brk = { 0 } }, /* 11b */ + { .mk = { 0x57, 0 }, .brk = { 0xd7, 0 } }, /* 11c */ + { .mk = { 0 }, .brk = { 0 } }, /* 11d */ + { .mk = { 0 }, .brk = { 0 } }, /* 11e */ + { .mk = { 0 }, .brk = { 0 } }, /* 11f */ + { .mk = { 0 }, .brk = { 0 } }, /* 120 */ + { .mk = { 0 }, .brk = { 0 } }, /* 121 */ + { .mk = { 0 }, .brk = { 0 } }, /* 122 */ + { .mk = { 0 }, .brk = { 0 } }, /* 123 */ + { .mk = { 0 }, .brk = { 0 } }, /* 124 */ + { .mk = { 0 }, .brk = { 0 } }, /* 125 */ + { .mk = { 0 }, .brk = { 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = { 0 }, .brk = { 0 } }, /* 12c */ + { .mk = { 0 }, .brk = { 0 } }, /* 12d */ + { .mk = { 0 }, .brk = { 0 } }, /* 12e */ + { .mk = { 0 }, .brk = { 0 } }, /* 12f */ + { .mk = { 0 }, .brk = { 0 } }, /* 130 */ + { .mk = { 0 }, .brk = { 0 } }, /* 131 */ + { .mk = { 0 }, .brk = { 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = { 0 }, .brk = { 0 } }, /* 134 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 137 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = { 0 }, .brk = { 0 } }, /* 13a */ + { .mk = { 0 }, .brk = { 0 } }, /* 13b */ + { .mk = { 0 }, .brk = { 0 } }, /* 13c */ + { .mk = { 0 }, .brk = { 0 } }, /* 13d */ + { .mk = { 0 }, .brk = { 0 } }, /* 13e */ + { .mk = { 0 }, .brk = { 0 } }, /* 13f */ + { .mk = { 0 }, .brk = { 0 } }, /* 140 */ + { .mk = { 0 }, .brk = { 0 } }, /* 141 */ + { .mk = { 0 }, .brk = { 0 } }, /* 142 */ + { .mk = { 0 }, .brk = { 0 } }, /* 143 */ + { .mk = { 0 }, .brk = { 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 146 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 147 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 148 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 14b */ + { .mk = { 0 }, .brk = { 0 } }, /* 14c */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 14d */ + { .mk = { 0 }, .brk = { 0 } }, /* 14e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 14f */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 150 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 151 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 152 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = { 0 }, .brk = { 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = { 0 }, .brk = { 0 } }, /* 157 */ + { .mk = { 0 }, .brk = { 0 } }, /* 158 */ + { .mk = { 0 }, .brk = { 0 } }, /* 159 */ + { .mk = { 0 }, .brk = { 0 } }, /* 15a */ + { .mk = { 0 }, .brk = { 0 } }, /* 15b */ + { .mk = { 0 }, .brk = { 0 } }, /* 15c */ + { .mk = { 0 }, .brk = { 0 } }, /* 15d */ + { .mk = { 0 }, .brk = { 0 } }, /* 15e */ + { .mk = { 0 }, .brk = { 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = { 0 }, .brk = { 0 } }, /* 161 */ + { .mk = { 0 }, .brk = { 0 } }, /* 162 */ + { .mk = { 0 }, .brk = { 0 } }, /* 163 */ + { .mk = { 0 }, .brk = { 0 } }, /* 164 */ + { .mk = { 0 }, .brk = { 0 } }, /* 165 */ + { .mk = { 0 }, .brk = { 0 } }, /* 166 */ + { .mk = { 0 }, .brk = { 0 } }, /* 167 */ + { .mk = { 0 }, .brk = { 0 } }, /* 168 */ + { .mk = { 0 }, .brk = { 0 } }, /* 169 */ + { .mk = { 0 }, .brk = { 0 } }, /* 16a */ + { .mk = { 0 }, .brk = { 0 } }, /* 16b */ + { .mk = { 0 }, .brk = { 0 } }, /* 16c */ + { .mk = { 0 }, .brk = { 0 } }, /* 16d */ + { .mk = { 0 }, .brk = { 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = { 0 }, .brk = { 0 } }, /* 170 */ + { .mk = { 0 }, .brk = { 0 } }, /* 171 */ + { .mk = { 0 }, .brk = { 0 } }, /* 172 */ + { .mk = { 0 }, .brk = { 0 } }, /* 173 */ + { .mk = { 0 }, .brk = { 0 } }, /* 174 */ + { .mk = { 0 }, .brk = { 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = { 0 }, .brk = { 0 } }, /* 177 */ + { .mk = { 0 }, .brk = { 0 } }, /* 178 */ + { .mk = { 0 }, .brk = { 0 } }, /* 179 */ + { .mk = { 0 }, .brk = { 0 } }, /* 17a */ + { .mk = { 0 }, .brk = { 0 } }, /* 17b */ + { .mk = { 0 }, .brk = { 0 } }, /* 17c */ + { .mk = { 0 }, .brk = { 0 } }, /* 17d */ + { .mk = { 0 }, .brk = { 0 } }, /* 17e */ + { .mk = { 0 }, .brk = { 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; static uint8_t crtcmask[32] = { @@ -511,6 +771,15 @@ recalc_address_sl(tandy_t *dev) } } +static void +vid_update_latch(t1kvid_t *vid) +{ + uint32_t lp_latch = vid->displine * vid->crtc[1]; + + vid->crtc[0x10] = (lp_latch >> 8) & 0x3f; + vid->crtc[0x11] = lp_latch & 0xff; +} + static void vid_out(uint16_t addr, uint8_t val, void *priv) { @@ -541,7 +810,10 @@ vid_out(uint16_t addr, uint8_t val, void *priv) break; case 0x03d8: + old = vid->mode; vid->mode = val; + if ((old ^ val) & 0x01) + recalc_timings(dev); if (!dev->is_sl2) update_cga16_color(vid->mode); break; @@ -554,6 +826,18 @@ vid_out(uint16_t addr, uint8_t val, void *priv) vid->array_index = val & 0x1f; break; + case 0x3db: + if (!dev->is_sl2 && (vid->lp_strobe == 1)) + vid->lp_strobe = 0; + break; + + case 0x3dc: + if (!dev->is_sl2 && (vid->lp_strobe == 0)) { + vid->lp_strobe = 1; + vid_update_latch(vid); + } + break; + case 0x03de: if (vid->array_index & 16) val &= 0xf; @@ -590,7 +874,7 @@ static uint8_t vid_in(uint16_t addr, void *priv) { const tandy_t *dev = (tandy_t *) priv; - const t1kvid_t *vid = dev->vid; + t1kvid_t *vid = dev->vid; uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) @@ -609,6 +893,18 @@ vid_in(uint16_t addr, void *priv) ret = vid->stat; break; + case 0x3db: + if (!dev->is_sl2 && (vid->lp_strobe == 1)) + vid->lp_strobe = 0; + break; + + case 0x3dc: + if (!dev->is_sl2 && (vid->lp_strobe == 0)) { + vid->lp_strobe = 1; + vid_update_latch(vid); + } + break; + default: break; } @@ -728,10 +1024,10 @@ vid_poll(void *priv) for (x = 0; x < vid->crtc[1]; x++) { dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; vid->ma++; - buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 8] = buffer32->line[vid->displine << 1][(x << 3) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 9] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 10] = buffer32->line[vid->displine << 1][(x << 3) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 11] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 12] = buffer32->line[vid->displine << 1][(x << 3) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 13] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 3) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 14] = buffer32->line[vid->displine << 1][(x << 3) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 3) + 15] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16; } } else if (vid->array[3] & 0x10) { /*160x200x16*/ for (x = 0; x < vid->crtc[1]; x++) { @@ -741,10 +1037,10 @@ vid_poll(void *priv) dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 3) * 0x2000) + 1]; } vid->ma++; - buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1]) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1]) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1]) + 16] + 16; - buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & vid->array[1]) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 8] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 8] = buffer32->line[vid->displine << 1][(x << 4) + 9] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 9] = buffer32->line[vid->displine << 1][(x << 4) + 10] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 10] = buffer32->line[vid->displine << 1][(x << 4) + 11] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 11] = vid->array[((dat >> 12) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 12] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 12] = buffer32->line[vid->displine << 1][(x << 4) + 13] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 13] = buffer32->line[vid->displine << 1][(x << 4) + 14] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 14] = buffer32->line[vid->displine << 1][(x << 4) + 15] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 15] = vid->array[((dat >> 8) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 16] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 16] = buffer32->line[vid->displine << 1][(x << 4) + 17] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 17] = buffer32->line[vid->displine << 1][(x << 4) + 18] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 18] = buffer32->line[vid->displine << 1][(x << 4) + 19] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 19] = vid->array[((dat >> 4) & vid->array[1] & 0x0f) + 16] + 16; + buffer32->line[vid->displine << 1][(x << 4) + 20] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 20] = buffer32->line[vid->displine << 1][(x << 4) + 21] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 21] = buffer32->line[vid->displine << 1][(x << 4) + 22] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 22] = buffer32->line[vid->displine << 1][(x << 4) + 23] = buffer32->line[(vid->displine << 1) + 1][(x << 4) + 23] = vid->array[(dat & vid->array[1] & 0x0f) + 16] + 16; } } else if (vid->array[3] & 0x08) { /*640x200x4 - this implementation is a complete guess!*/ for (x = 0; x < vid->crtc[1]; x++) { @@ -962,6 +1258,7 @@ vid_poll(void *priv) vid->dispon = 0; vid->displine = 0; vid->vsynctime = 16; + picint(1 << 5); if (vid->crtc[7]) { if (vid->mode & 1) x = (vid->crtc[1] << 3) + 16; @@ -1065,11 +1362,10 @@ vid_init(tandy_t *dev) vid = malloc(sizeof(t1kvid_t)); memset(vid, 0x00, sizeof(t1kvid_t)); vid->memctrl = -1; - dev->vid = vid; video_inform(VIDEO_FLAG_TYPE_CGA, &timing_dram); - display_type = machine_get_config_int("display_type"); + display_type = device_get_config_int("display_type"); vid->composite = (display_type != TANDY_RGB); cga_comp_init(1); @@ -1082,11 +1378,14 @@ vid_init(tandy_t *dev) io_sethandler(0x0065, 1, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); } else vid->b8000_mask = 0x3fff; + timer_add(&vid->timer, vid_poll, dev, 1); mem_mapping_add(&vid->mapping, 0xb8000, 0x08000, vid_read, NULL, NULL, vid_write, NULL, NULL, NULL, 0, dev); io_sethandler(0x03d0, 16, vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + + dev->vid = vid; } const device_config_t vid_config[] = { @@ -1320,12 +1619,12 @@ tandy_write(uint16_t addr, uint8_t val, void *priv) switch (addr) { case 0x00a0: - if (val & 0x10) { + if (dev->is_hx && (val & 0x10)) { dev->base = (mem_size - 256) * 1024; dev->mask = 0x3ffff; mem_mapping_set_addr(&ram_low_mapping, 0, dev->base); mem_mapping_set_addr(&dev->ram_mapping, - ((val >> 1) & 7) * 128 * 1024, 0x40000); + (((val >> 1) & 7) - 1) * 128 * 1024, 0x40000); } else { dev->base = (mem_size - 128) * 1024; dev->mask = 0x1ffff; @@ -1333,6 +1632,22 @@ tandy_write(uint16_t addr, uint8_t val, void *priv) mem_mapping_set_addr(&dev->ram_mapping, ((val >> 1) & 7) * 128 * 1024, 0x20000); } + if (dev->is_hx) { + io_removehandler(0x03d0, 16, + vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + if (val & 0x01) + mem_mapping_disable(&dev->vid->mapping); + else { + io_sethandler(0x03d0, 16, + vid_in, NULL, NULL, vid_out, NULL, NULL, dev); + mem_mapping_set_addr(&dev->vid->mapping, 0xb8000, 0x8000); + } + } else { + if (val & 0x01) + mem_mapping_set_addr(&dev->vid->mapping, 0xc0000, 0x10000); + else + mem_mapping_set_addr(&dev->vid->mapping, 0xb8000, 0x8000); + } dev->ram_bank = val; break; @@ -1462,8 +1777,7 @@ machine_tandy1k_init(const machine_t *model, int type) { tandy_t *dev; - dev = malloc(sizeof(tandy_t)); - memset(dev, 0x00, sizeof(tandy_t)); + dev = calloc(1, sizeof(tandy_t)); machine_common_init(model); @@ -1482,27 +1796,33 @@ machine_tandy1k_init(const machine_t *model, int type) device_add(&keyboard_tandy_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_tandy_device); video_reset(gfxcard[0]); switch (type) { case TYPE_TANDY: + case TYPE_TANDY1000SX: keyboard_set_table(scancode_tandy); io_sethandler(0x00a0, 1, tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); + device_context(&vid_device); vid_init(dev); + device_context_restore(); device_add_ex(&vid_device, dev); - device_add(&sn76489_device); + device_add((type == TYPE_TANDY1000SX) ? &ncr8496_device : &sn76489_device); break; case TYPE_TANDY1000HX: + dev->is_hx = 1; keyboard_set_table(scancode_tandy); io_sethandler(0x00a0, 1, tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); + device_context(&vid_device_hx); vid_init(dev); - device_add_ex(&vid_device, dev); + device_context_restore(); + device_add_ex(&vid_device_hx, dev); device_add(&ncr8496_device); device_add(&eep_1000hx_device); break; @@ -1512,7 +1832,9 @@ machine_tandy1k_init(const machine_t *model, int type) init_rom(dev); io_sethandler(0xffe8, 8, tandy_read, NULL, NULL, tandy_write, NULL, NULL, dev); + device_context(&vid_device_sl); vid_init(dev); + device_context_restore(); device_add_ex(&vid_device_sl, dev); device_add(&pssj_device); device_add(&eep_1000sl2_device); @@ -1534,7 +1856,7 @@ tandy1k_eeprom_read(void) } int -machine_tandy_init(const machine_t *model) +machine_tandy1000sx_init(const machine_t *model) { int ret; @@ -1544,7 +1866,7 @@ machine_tandy_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_tandy1k_init(model, TYPE_TANDY); + machine_tandy1k_init(model, TYPE_TANDY1000SX); return ret; } diff --git a/src/machine/m_v86p.c b/src/machine/m_v86p.c index 54af9b0535..f152383d19 100644 --- a/src/machine/m_v86p.c +++ b/src/machine/m_v86p.c @@ -88,13 +88,13 @@ machine_v86p_init(const machine_t *model) device_add(&keyboard_xt_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); if (gfxcard[0] == VID_INTERNAL) device_add(&f82c425_video_device); - if (hdc_current <= 1) + if (hdc_current[0] <= HDC_INTERNAL) device_add(&st506_xt_victor_v86p_device); return ret; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index ded68f5dc3..c11968d335 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -23,15 +23,15 @@ extern const device_t vendex_xt_rtc_onboard_device; static void -machine_xt_common_init(const machine_t *model) +machine_xt_common_init(const machine_t *model, int fixed_floppy) { + if ((fdc_current[0] == FDC_INTERNAL) || fixed_floppy) + device_add(&fdc_xt_device); + machine_common_init(model); pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); - if (fdc_type == FDC_INTERNAL) - device_add(&fdc_xt_device); - nmi_init(); standalone_gameport_type = &gameport_device; } @@ -59,7 +59,7 @@ machine_pc_init(const machine_t *model) device_add(&keyboard_pc_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } @@ -93,19 +93,11 @@ machine_pc82_init(const machine_t *model) device_add(&keyboard_pc82_device); device_add(&ibm_5161_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } -static void -machine_xt_init_ex(const machine_t *model) -{ - device_add(&keyboard_xt_device); - - machine_xt_common_init(model); -} - int machine_xt_init(const machine_t *model) { @@ -127,10 +119,12 @@ machine_xt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_init_ex(model); + device_add(&keyboard_xt_device); device_add(&ibm_5161_device); + machine_xt_common_init(model, 0); + return ret; } @@ -145,7 +139,9 @@ machine_genxt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_init_ex(model); + device_add(&keyboard_xt_device); + + machine_xt_common_init(model, 0); return ret; } @@ -170,17 +166,17 @@ machine_xt86_init(const machine_t *model) device_add(&keyboard_xt86_device); device_add(&ibm_5161_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } static void -machine_xt_clone_init(const machine_t *model) +machine_xt_clone_init(const machine_t *model, int fixed_floppy) { device_add(&keyboard_xtclone_device); - machine_xt_common_init(model); + machine_xt_common_init(model, fixed_floppy); } int @@ -194,7 +190,7 @@ machine_xt_americxt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -210,7 +206,7 @@ machine_xt_amixt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -226,7 +222,7 @@ machine_xt_znic_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -242,7 +238,7 @@ machine_xt_dtk_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -258,7 +254,7 @@ machine_xt_jukopc_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -274,7 +270,7 @@ machine_xt_openxt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -294,7 +290,7 @@ machine_xt_pcxt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -312,7 +308,7 @@ machine_xt_pxxt_init(const machine_t *model) device_add(&keyboard_xt_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } @@ -329,7 +325,7 @@ machine_xt_iskra3104_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -363,7 +359,25 @@ machine_xt_pravetz16_imko4_init(const machine_t *model) device_add(&keyboard_pravetz_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); + + return ret; +} + +int +machine_xt_pravetz16s_cpu12p_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/pravetz16s/PR16S.BIN", + 0x000fe000, 8192, 0); + + if (bios_only || !ret) + return ret; + + device_add(&keyboard_xt_device); + + machine_xt_common_init(model, 0); return ret; } @@ -379,7 +393,10 @@ machine_xt_micoms_xl7turbo_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_init_ex(model); + device_add(&keyboard_xt_device); + + machine_xt_common_init(model, 0); + return ret; } @@ -394,7 +411,7 @@ machine_xt_pc4i_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -412,7 +429,7 @@ machine_xt_mpc1600_init(const machine_t *model) device_add(&keyboard_pc82_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } @@ -435,7 +452,7 @@ machine_xt_pcspirit_init(const machine_t *model) device_add(&keyboard_pc82_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } @@ -453,7 +470,7 @@ machine_xt_pc700_init(const machine_t *model) device_add(&keyboard_pc_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } @@ -471,7 +488,7 @@ machine_xt_pc500_init(const machine_t *model) device_add(&keyboard_pc_device); - machine_xt_common_init(model); + machine_xt_common_init(model, 0); return ret; } @@ -487,18 +504,20 @@ machine_xt_vendex_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + /* On-board FDC cannot be disabled */ + machine_xt_clone_init(model, 1); + device_add(&vendex_xt_rtc_onboard_device); return ret; } static void -machine_xt_hyundai_common_init(const machine_t *model) +machine_xt_hyundai_common_init(const machine_t *model, int fixed_floppy) { device_add(&keyboard_xt_hyundai_device); - machine_xt_common_init(model); + machine_xt_common_init(model, fixed_floppy); } int @@ -512,10 +531,8 @@ machine_xt_super16t_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_hyundai_common_init(model); - /* On-board FDC cannot be disabled */ - device_add(&fdc_xt_device); + machine_xt_hyundai_common_init(model, 1); return ret; } @@ -531,10 +548,8 @@ machine_xt_super16te_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_hyundai_common_init(model); - /* On-board FDC cannot be disabled */ - device_add(&fdc_xt_device); + machine_xt_hyundai_common_init(model, 1); return ret; } @@ -550,10 +565,8 @@ machine_xt_top88_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); - /* On-board FDC cannot be disabled */ - device_add(&fdc_xt_device); + machine_xt_clone_init(model, 1); return ret; } @@ -569,7 +582,7 @@ machine_xt_kaypropc_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -585,10 +598,8 @@ machine_xt_sansx16_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); - /* On-board FDC cannot be disabled */ - device_add(&fdc_xt_device); + machine_xt_clone_init(model, 1); return ret; } @@ -604,7 +615,7 @@ machine_xt_bw230_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -620,7 +631,7 @@ machine_xt_v20xt_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -636,7 +647,7 @@ machine_xt_pb8810_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_clone_init(model); + machine_xt_clone_init(model, 0); return ret; } @@ -652,7 +663,9 @@ machine_xt_glabios_init(const machine_t *model) if (bios_only || !ret) return ret; - machine_xt_init_ex(model); + device_add(&keyboard_xt_device); + + machine_xt_common_init(model, 0); return ret; } diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index f5dca48a7a..ed1b3e26cf 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -53,7 +53,7 @@ machine_xt_compaq_deskpro_init(const machine_t *model) pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_compaq_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); nmi_init(); standalone_gameport_type = &gameport_device; @@ -80,7 +80,7 @@ machine_xt_compaq_portable_init(const machine_t *model) pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); device_add(&keyboard_xt_compaq_device); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); nmi_init(); if (joystick_type) diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 87c2fe3623..877d26ff55 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -147,7 +147,7 @@ machine_xt_laserxt_common_init(const machine_t *model,int is_lxt3) pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); nmi_init(); diff --git a/src/machine/m_xt_olivetti.c b/src/machine/m_xt_olivetti.c index 7806d378b6..817b0d0cc2 100644 --- a/src/machine/m_xt_olivetti.c +++ b/src/machine/m_xt_olivetti.c @@ -591,7 +591,7 @@ m24_kbd_write(uint16_t port, uint8_t val, void *priv) * bit 7 - use BIOS HD on mainboard (on) / on controller (off) * bit 6 - use OCG/CGA display adapter (on) / other display adapter (off) */ - ret = (hdc_current == HDC_INTERNAL) ? 0x00 : 0x80; + ret = (hdc_current[0] == HDC_INTERNAL) ? 0x00 : 0x80; ret |= video_is_cga() ? 0x40 : 0x00; m24_kbd_adddata(ret); @@ -846,262 +846,518 @@ ms_poll(void *priv) */ const scancode scancode_olivetti_m24_deluxe[512] = { // clang-format off - { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, - { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, - { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, - { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, - { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, - { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, - { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, - { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, - { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, - { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, - { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, - { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, - { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, - { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, - { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, - { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, - { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, - { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, - { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, - { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, - { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, - { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, - { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, - { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, - { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, - { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, - { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, - { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, - { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, - { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, - { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, - { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, - { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, - { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, - { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, - { {0}, {0} }, { {0}, {0} }, - { {0x5e, 0}, {0xde, 0} }, { {0x60, 0}, {0xe0, 0} }, /*054*/ - { {0x61, 0}, {0xe1, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*058*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*05c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*060*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*064*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*068*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*06c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*070*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*074*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*078*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*07c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*080*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*084*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*088*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*08c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*090*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*094*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*098*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*09c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0fc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*100*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*104*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*108*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*10c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*110*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*114*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*118*/ - { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*11c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*120*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*124*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*128*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*12c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*130*/ - { {0}, {0} }, { {0x5f, 0}, {0xdf, 0} }, - { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ - { {0x66, 0}, {0xe6, 0} }, { {0x55, 0}, {0xd5, 0} }, - { {0}, {0} }, { {0}, {0} }, /*138*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*13c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*140*/ - { {0}, {0} }, { {0}, {0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x63, 0}, {0xe3, 0} }, /*144*/ - { {0x5b, 0}, {0xdb, 0} }, { {0x5c, 0}, {0xdc, 0} }, - { {0}, {0} }, { {0x58, 0}, {0xd8, 0} }, /*148*/ - { {0}, {0} }, { {0x5a, 0}, {0xda, 0} }, - { {0}, {0} }, { {0x65, 0}, {0xe5, 0} }, /*14c*/ - { {0x59, 0}, {0xd9, 0} }, { {0x5d, 0}, {0xdd, 0} }, - { {0x62, 0}, {0xe2, 0} }, { {0x64, 0}, {0xe4, 0} }, /*150*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*154*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0x54, 0}, {0xd4, 0} }, /*158*/ - { {0x67, 0}, {0xe7, 0} }, { {0x56, 0}, {0xd6, 0} }, - { {0}, {0} }, { {0}, {0} }, /*15c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*160*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*164*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*168*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*16c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*170*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*174*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*148*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*17c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*180*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*184*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*188*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*18c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*190*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*194*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*198*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*19c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 013 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 022 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0 }, .brk = { 0 } }, /* 054 */ + { .mk = { 0 }, .brk = { 0 } }, /* 055 */ + { .mk = { 0x5e, 0 }, .brk = { 0xde, 0 } }, /* 056 */ + { .mk = { 0x60, 0 }, .brk = { 0xe0, 0 } }, /* 057 */ + { .mk = { 0x61, 0 }, .brk = { 0xe1, 0 } }, /* 058 */ + { .mk = { 0 }, .brk = { 0 } }, /* 059 */ + { .mk = { 0 }, .brk = { 0 } }, /* 05a */ + { .mk = { 0 }, .brk = { 0 } }, /* 05b */ + { .mk = { 0 }, .brk = { 0 } }, /* 05c */ + { .mk = { 0 }, .brk = { 0 } }, /* 05d */ + { .mk = { 0 }, .brk = { 0 } }, /* 05e */ + { .mk = { 0 }, .brk = { 0 } }, /* 05f */ + { .mk = { 0 }, .brk = { 0 } }, /* 060 */ + { .mk = { 0 }, .brk = { 0 } }, /* 061 */ + { .mk = { 0 }, .brk = { 0 } }, /* 062 */ + { .mk = { 0 }, .brk = { 0 } }, /* 063 */ + { .mk = { 0 }, .brk = { 0 } }, /* 064 */ + { .mk = { 0 }, .brk = { 0 } }, /* 065 */ + { .mk = { 0 }, .brk = { 0 } }, /* 066 */ + { .mk = { 0 }, .brk = { 0 } }, /* 067 */ + { .mk = { 0 }, .brk = { 0 } }, /* 068 */ + { .mk = { 0 }, .brk = { 0 } }, /* 069 */ + { .mk = { 0 }, .brk = { 0 } }, /* 06a */ + { .mk = { 0 }, .brk = { 0 } }, /* 06b */ + { .mk = { 0 }, .brk = { 0 } }, /* 06c */ + { .mk = { 0 }, .brk = { 0 } }, /* 06d */ + { .mk = { 0 }, .brk = { 0 } }, /* 06e */ + { .mk = { 0 }, .brk = { 0 } }, /* 06f */ + { .mk = { 0 }, .brk = { 0 } }, /* 070 */ + { .mk = { 0 }, .brk = { 0 } }, /* 071 */ + { .mk = { 0 }, .brk = { 0 } }, /* 072 */ + { .mk = { 0 }, .brk = { 0 } }, /* 073 */ + { .mk = { 0 }, .brk = { 0 } }, /* 074 */ + { .mk = { 0 }, .brk = { 0 } }, /* 075 */ + { .mk = { 0 }, .brk = { 0 } }, /* 076 */ + { .mk = { 0 }, .brk = { 0 } }, /* 077 */ + { .mk = { 0 }, .brk = { 0 } }, /* 078 */ + { .mk = { 0 }, .brk = { 0 } }, /* 079 */ + { .mk = { 0 }, .brk = { 0 } }, /* 07a */ + { .mk = { 0 }, .brk = { 0 } }, /* 07b */ + { .mk = { 0 }, .brk = { 0 } }, /* 07c */ + { .mk = { 0 }, .brk = { 0 } }, /* 07d */ + { .mk = { 0 }, .brk = { 0 } }, /* 07e */ + { .mk = { 0 }, .brk = { 0 } }, /* 07f */ + { .mk = { 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = { 0 }, .brk = { 0 } }, /* 100 */ + { .mk = { 0 }, .brk = { 0 } }, /* 101 */ + { .mk = { 0 }, .brk = { 0 } }, /* 102 */ + { .mk = { 0 }, .brk = { 0 } }, /* 103 */ + { .mk = { 0 }, .brk = { 0 } }, /* 104 */ + { .mk = { 0 }, .brk = { 0 } }, /* 105 */ + { .mk = { 0 }, .brk = { 0 } }, /* 106 */ + { .mk = { 0 }, .brk = { 0 } }, /* 107 */ + { .mk = { 0 }, .brk = { 0 } }, /* 108 */ + { .mk = { 0 }, .brk = { 0 } }, /* 109 */ + { .mk = { 0 }, .brk = { 0 } }, /* 10a */ + { .mk = { 0 }, .brk = { 0 } }, /* 10b */ + { .mk = { 0 }, .brk = { 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = { 0 }, .brk = { 0 } }, /* 10e */ + { .mk = { 0 }, .brk = { 0 } }, /* 10f */ + { .mk = { 0 }, .brk = { 0 } }, /* 110 */ + { .mk = { 0 }, .brk = { 0 } }, /* 111 */ + { .mk = { 0 }, .brk = { 0 } }, /* 112 */ + { .mk = { 0 }, .brk = { 0 } }, /* 113 */ + { .mk = { 0 }, .brk = { 0 } }, /* 114 */ + { .mk = { 0 }, .brk = { 0 } }, /* 115 */ + { .mk = { 0 }, .brk = { 0 } }, /* 116 */ + { .mk = { 0 }, .brk = { 0 } }, /* 117 */ + { .mk = { 0 }, .brk = { 0 } }, /* 118 */ + { .mk = { 0 }, .brk = { 0 } }, /* 119 */ + { .mk = { 0 }, .brk = { 0 } }, /* 11a */ + { .mk = { 0 }, .brk = { 0 } }, /* 11b */ + { .mk = { 0x57, 0 }, .brk = { 0xd7, 0 } }, /* 11c */ + { .mk = { 0 }, .brk = { 0 } }, /* 11d */ + { .mk = { 0 }, .brk = { 0 } }, /* 11e */ + { .mk = { 0 }, .brk = { 0 } }, /* 11f */ + { .mk = { 0 }, .brk = { 0 } }, /* 120 */ + { .mk = { 0 }, .brk = { 0 } }, /* 121 */ + { .mk = { 0 }, .brk = { 0 } }, /* 122 */ + { .mk = { 0 }, .brk = { 0 } }, /* 123 */ + { .mk = { 0 }, .brk = { 0 } }, /* 124 */ + { .mk = { 0 }, .brk = { 0 } }, /* 125 */ + { .mk = { 0 }, .brk = { 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = { 0 }, .brk = { 0 } }, /* 12c */ + { .mk = { 0 }, .brk = { 0 } }, /* 12d */ + { .mk = { 0 }, .brk = { 0 } }, /* 12e */ + { .mk = { 0 }, .brk = { 0 } }, /* 12f */ + { .mk = { 0 }, .brk = { 0 } }, /* 130 */ + { .mk = { 0 }, .brk = { 0 } }, /* 131 */ + { .mk = { 0 }, .brk = { 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = { 0 }, .brk = { 0 } }, /* 134 */ + { .mk = { 0x5f, 0 }, .brk = { 0xdf, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 137 */ + { .mk = { 0x66, 0 }, .brk = { 0xe6, 0 } }, /* 138 */ + { .mk = { 0x55, 0 }, .brk = { 0xd5, 0 } }, /* 139 */ + { .mk = { 0 }, .brk = { 0 } }, /* 13a */ + { .mk = { 0 }, .brk = { 0 } }, /* 13b */ + { .mk = { 0 }, .brk = { 0 } }, /* 13c */ + { .mk = { 0 }, .brk = { 0 } }, /* 13d */ + { .mk = { 0 }, .brk = { 0 } }, /* 13e */ + { .mk = { 0 }, .brk = { 0 } }, /* 13f */ + { .mk = { 0 }, .brk = { 0 } }, /* 140 */ + { .mk = { 0 }, .brk = { 0 } }, /* 141 */ + { .mk = { 0 }, .brk = { 0 } }, /* 142 */ + { .mk = { 0 }, .brk = { 0 } }, /* 143 */ + { .mk = { 0 }, .brk = { 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 146 */ + { .mk = { 0x63, 0 }, .brk = { 0xe3, 0 } }, /* 147 */ + { .mk = { 0x5b, 0 }, .brk = { 0xdb, 0 } }, /* 148 */ + { .mk = { 0x5c, 0 }, .brk = { 0xdc, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = { 0x58, 0 }, .brk = { 0xd8, 0 } }, /* 14b */ + { .mk = { 0 }, .brk = { 0 } }, /* 14c */ + { .mk = { 0x5a, 0 }, .brk = { 0xda, 0 } }, /* 14d */ + { .mk = { 0 }, .brk = { 0 } }, /* 14e */ + { .mk = { 0x65, 0 }, .brk = { 0xe5, 0 } }, /* 14f */ + { .mk = { 0x59, 0 }, .brk = { 0xd9, 0 } }, /* 150 */ + { .mk = { 0x5d, 0 }, .brk = { 0xdd, 0 } }, /* 151 */ + { .mk = { 0x62, 0 }, .brk = { 0xe2, 0 } }, /* 152 */ + { .mk = { 0x64, 0 }, .brk = { 0xe4, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = { 0 }, .brk = { 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = { 0 }, .brk = { 0 } }, /* 157 */ + { .mk = { 0 }, .brk = { 0 } }, /* 158 */ + { .mk = { 0 }, .brk = { 0 } }, /* 159 */ + { .mk = { 0 }, .brk = { 0 } }, /* 15a */ + { .mk = { 0x54, 0 }, .brk = { 0xd4, 0 } }, /* 15b */ + { .mk = { 0x67, 0 }, .brk = { 0xe7, 0 } }, /* 15c */ + { .mk = { 0x56, 0 }, .brk = { 0xd6, 0 } }, /* 15d */ + { .mk = { 0 }, .brk = { 0 } }, /* 15e */ + { .mk = { 0 }, .brk = { 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = { 0 }, .brk = { 0 } }, /* 161 */ + { .mk = { 0 }, .brk = { 0 } }, /* 162 */ + { .mk = { 0 }, .brk = { 0 } }, /* 163 */ + { .mk = { 0 }, .brk = { 0 } }, /* 164 */ + { .mk = { 0 }, .brk = { 0 } }, /* 165 */ + { .mk = { 0 }, .brk = { 0 } }, /* 166 */ + { .mk = { 0 }, .brk = { 0 } }, /* 167 */ + { .mk = { 0 }, .brk = { 0 } }, /* 168 */ + { .mk = { 0 }, .brk = { 0 } }, /* 169 */ + { .mk = { 0 }, .brk = { 0 } }, /* 16a */ + { .mk = { 0 }, .brk = { 0 } }, /* 16b */ + { .mk = { 0 }, .brk = { 0 } }, /* 16c */ + { .mk = { 0 }, .brk = { 0 } }, /* 16d */ + { .mk = { 0 }, .brk = { 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = { 0 }, .brk = { 0 } }, /* 170 */ + { .mk = { 0 }, .brk = { 0 } }, /* 171 */ + { .mk = { 0 }, .brk = { 0 } }, /* 172 */ + { .mk = { 0 }, .brk = { 0 } }, /* 173 */ + { .mk = { 0 }, .brk = { 0 } }, /* 174 */ + { .mk = { 0 }, .brk = { 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = { 0 }, .brk = { 0 } }, /* 177 */ + { .mk = { 0 }, .brk = { 0 } }, /* 178 */ + { .mk = { 0 }, .brk = { 0 } }, /* 179 */ + { .mk = { 0 }, .brk = { 0 } }, /* 17a */ + { .mk = { 0 }, .brk = { 0 } }, /* 17b */ + { .mk = { 0 }, .brk = { 0 } }, /* 17c */ + { .mk = { 0 }, .brk = { 0 } }, /* 17d */ + { .mk = { 0 }, .brk = { 0 } }, /* 17e */ + { .mk = { 0 }, .brk = { 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; @@ -1113,262 +1369,518 @@ const scancode scancode_olivetti_m24_deluxe[512] = { */ const scancode scancode_olivetti_m240[512] = { // clang-format off - { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, - { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} }, - { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, - { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} }, - { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, - { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} }, - { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, - { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} }, - { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, - { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} }, - { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, - { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} }, - { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, - { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} }, - { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} }, - { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, - { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} }, - { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, - { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} }, - { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, - { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} }, - { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, - { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} }, - { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, - { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} }, - { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, - { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, - { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, - { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} }, - { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, - { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} }, - { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, - { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} }, - { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} }, - { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} }, - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*054*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*058*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*05c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*060*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*064*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*068*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*06c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*070*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*074*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*078*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*07c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*080*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*084*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*088*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*08c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*090*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*094*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*098*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*09c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*0fc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*100*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*104*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*108*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*10c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*110*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*114*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*118*/ - { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, - { {0}, {0} }, { {0}, {0} }, /*11c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*120*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*124*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*128*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*12c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*130*/ - { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, - { {0}, {0} }, { {0x37, 0}, {0xb7, 0} }, /*134*/ - { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*138*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*13c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*140*/ - { {0}, {0} }, { {0}, {0} }, - { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*144*/ - { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, - { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*148*/ - { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, - { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*14c*/ - { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, - { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*150*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*154*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*158*/ - { {0}, {0} }, { {0x54, 0}, {0xd4, 0} }, - { {0x56, 0}, {0xd6, 0} }, { {0x5c, 0}, {0xdc, 0} }, /*15c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*160*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*164*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*168*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*16c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*170*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*174*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*148*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*17c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*180*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*184*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*188*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*18c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*190*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*194*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*198*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*19c*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1a8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ac*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1b8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1bc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1c8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1cc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1d8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1dc*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1e8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1ec*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f0*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f4*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} }, /*1f8*/ - { {0}, {0} }, { {0}, {0} }, - { {0}, {0} }, { {0}, {0} } /*1fc*/ + { .mk = { 0 }, .brk = { 0 } }, /* 000 */ + { .mk = { 0x01, 0 }, .brk = { 0x81, 0 } }, /* 001 */ + { .mk = { 0x02, 0 }, .brk = { 0x82, 0 } }, /* 002 */ + { .mk = { 0x03, 0 }, .brk = { 0x83, 0 } }, /* 003 */ + { .mk = { 0x04, 0 }, .brk = { 0x84, 0 } }, /* 004 */ + { .mk = { 0x05, 0 }, .brk = { 0x85, 0 } }, /* 005 */ + { .mk = { 0x06, 0 }, .brk = { 0x86, 0 } }, /* 006 */ + { .mk = { 0x07, 0 }, .brk = { 0x87, 0 } }, /* 007 */ + { .mk = { 0x08, 0 }, .brk = { 0x88, 0 } }, /* 008 */ + { .mk = { 0x09, 0 }, .brk = { 0x89, 0 } }, /* 009 */ + { .mk = { 0x0a, 0 }, .brk = { 0x8a, 0 } }, /* 00a */ + { .mk = { 0x0b, 0 }, .brk = { 0x8b, 0 } }, /* 00b */ + { .mk = { 0x0c, 0 }, .brk = { 0x8c, 0 } }, /* 00c */ + { .mk = { 0x0d, 0 }, .brk = { 0x8d, 0 } }, /* 00d */ + { .mk = { 0x0e, 0 }, .brk = { 0x8e, 0 } }, /* 00e */ + { .mk = { 0x0f, 0 }, .brk = { 0x8f, 0 } }, /* 00f */ + { .mk = { 0x10, 0 }, .brk = { 0x90, 0 } }, /* 010 */ + { .mk = { 0x11, 0 }, .brk = { 0x91, 0 } }, /* 011 */ + { .mk = { 0x12, 0 }, .brk = { 0x92, 0 } }, /* 012 */ + { .mk = { 0x13, 0 }, .brk = { 0x93, 0 } }, /* 013 */ + { .mk = { 0x14, 0 }, .brk = { 0x94, 0 } }, /* 014 */ + { .mk = { 0x15, 0 }, .brk = { 0x95, 0 } }, /* 015 */ + { .mk = { 0x16, 0 }, .brk = { 0x96, 0 } }, /* 016 */ + { .mk = { 0x17, 0 }, .brk = { 0x97, 0 } }, /* 017 */ + { .mk = { 0x18, 0 }, .brk = { 0x98, 0 } }, /* 018 */ + { .mk = { 0x19, 0 }, .brk = { 0x99, 0 } }, /* 019 */ + { .mk = { 0x1a, 0 }, .brk = { 0x9a, 0 } }, /* 01a */ + { .mk = { 0x1b, 0 }, .brk = { 0x9b, 0 } }, /* 01b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 01c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 01d */ + { .mk = { 0x1e, 0 }, .brk = { 0x9e, 0 } }, /* 01e */ + { .mk = { 0x1f, 0 }, .brk = { 0x9f, 0 } }, /* 01f */ + { .mk = { 0x20, 0 }, .brk = { 0xa0, 0 } }, /* 020 */ + { .mk = { 0x21, 0 }, .brk = { 0xa1, 0 } }, /* 021 */ + { .mk = { 0x22, 0 }, .brk = { 0xa2, 0 } }, /* 023 */ + { .mk = { 0x23, 0 }, .brk = { 0xa3, 0 } }, /* 023 */ + { .mk = { 0x24, 0 }, .brk = { 0xa4, 0 } }, /* 024 */ + { .mk = { 0x25, 0 }, .brk = { 0xa5, 0 } }, /* 025 */ + { .mk = { 0x26, 0 }, .brk = { 0xa6, 0 } }, /* 026 */ + { .mk = { 0x27, 0 }, .brk = { 0xa7, 0 } }, /* 027 */ + { .mk = { 0x28, 0 }, .brk = { 0xa8, 0 } }, /* 028 */ + { .mk = { 0x29, 0 }, .brk = { 0xa9, 0 } }, /* 029 */ + { .mk = { 0x2a, 0 }, .brk = { 0xaa, 0 } }, /* 02a */ + { .mk = { 0x2b, 0 }, .brk = { 0xab, 0 } }, /* 02b */ + { .mk = { 0x2c, 0 }, .brk = { 0xac, 0 } }, /* 02c */ + { .mk = { 0x2d, 0 }, .brk = { 0xad, 0 } }, /* 02d */ + { .mk = { 0x2e, 0 }, .brk = { 0xae, 0 } }, /* 02e */ + { .mk = { 0x2f, 0 }, .brk = { 0xaf, 0 } }, /* 02f */ + { .mk = { 0x30, 0 }, .brk = { 0xb0, 0 } }, /* 030 */ + { .mk = { 0x31, 0 }, .brk = { 0xb1, 0 } }, /* 031 */ + { .mk = { 0x32, 0 }, .brk = { 0xb2, 0 } }, /* 032 */ + { .mk = { 0x33, 0 }, .brk = { 0xb3, 0 } }, /* 033 */ + { .mk = { 0x34, 0 }, .brk = { 0xb4, 0 } }, /* 034 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 035 */ + { .mk = { 0x36, 0 }, .brk = { 0xb6, 0 } }, /* 036 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 037 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 038 */ + { .mk = { 0x39, 0 }, .brk = { 0xb9, 0 } }, /* 039 */ + { .mk = { 0x3a, 0 }, .brk = { 0xba, 0 } }, /* 03a */ + { .mk = { 0x3b, 0 }, .brk = { 0xbb, 0 } }, /* 03b */ + { .mk = { 0x3c, 0 }, .brk = { 0xbc, 0 } }, /* 03c */ + { .mk = { 0x3d, 0 }, .brk = { 0xbd, 0 } }, /* 03d */ + { .mk = { 0x3e, 0 }, .brk = { 0xbe, 0 } }, /* 03e */ + { .mk = { 0x3f, 0 }, .brk = { 0xbf, 0 } }, /* 03f */ + { .mk = { 0x40, 0 }, .brk = { 0xc0, 0 } }, /* 040 */ + { .mk = { 0x41, 0 }, .brk = { 0xc1, 0 } }, /* 041 */ + { .mk = { 0x42, 0 }, .brk = { 0xc2, 0 } }, /* 042 */ + { .mk = { 0x43, 0 }, .brk = { 0xc3, 0 } }, /* 043 */ + { .mk = { 0x44, 0 }, .brk = { 0xc4, 0 } }, /* 044 */ + { .mk = { 0x45, 0 }, .brk = { 0xc5, 0 } }, /* 045 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 046 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 047 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 048 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 049 */ + { .mk = { 0x4a, 0 }, .brk = { 0xca, 0 } }, /* 04a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 04b */ + { .mk = { 0x4c, 0 }, .brk = { 0xcc, 0 } }, /* 04c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 04d */ + { .mk = { 0x4e, 0 }, .brk = { 0xce, 0 } }, /* 04e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 04f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 050 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 051 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 052 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 053 */ + { .mk = { 0 }, .brk = { 0 } }, /* 054 */ + { .mk = { 0 }, .brk = { 0 } }, /* 055 */ + { .mk = { 0 }, .brk = { 0 } }, /* 056 */ + { .mk = { 0 }, .brk = { 0 } }, /* 057 */ + { .mk = { 0 }, .brk = { 0 } }, /* 058 */ + { .mk = { 0 }, .brk = { 0 } }, /* 059 */ + { .mk = { 0 }, .brk = { 0 } }, /* 05a */ + { .mk = { 0 }, .brk = { 0 } }, /* 05b */ + { .mk = { 0 }, .brk = { 0 } }, /* 05c */ + { .mk = { 0 }, .brk = { 0 } }, /* 05d */ + { .mk = { 0 }, .brk = { 0 } }, /* 05e */ + { .mk = { 0 }, .brk = { 0 } }, /* 05f */ + { .mk = { 0 }, .brk = { 0 } }, /* 060 */ + { .mk = { 0 }, .brk = { 0 } }, /* 061 */ + { .mk = { 0 }, .brk = { 0 } }, /* 062 */ + { .mk = { 0 }, .brk = { 0 } }, /* 063 */ + { .mk = { 0 }, .brk = { 0 } }, /* 064 */ + { .mk = { 0 }, .brk = { 0 } }, /* 065 */ + { .mk = { 0 }, .brk = { 0 } }, /* 066 */ + { .mk = { 0 }, .brk = { 0 } }, /* 067 */ + { .mk = { 0 }, .brk = { 0 } }, /* 068 */ + { .mk = { 0 }, .brk = { 0 } }, /* 069 */ + { .mk = { 0 }, .brk = { 0 } }, /* 06a */ + { .mk = { 0 }, .brk = { 0 } }, /* 06b */ + { .mk = { 0 }, .brk = { 0 } }, /* 06c */ + { .mk = { 0 }, .brk = { 0 } }, /* 06d */ + { .mk = { 0 }, .brk = { 0 } }, /* 06e */ + { .mk = { 0 }, .brk = { 0 } }, /* 06f */ + { .mk = { 0 }, .brk = { 0 } }, /* 070 */ + { .mk = { 0 }, .brk = { 0 } }, /* 071 */ + { .mk = { 0 }, .brk = { 0 } }, /* 072 */ + { .mk = { 0 }, .brk = { 0 } }, /* 073 */ + { .mk = { 0 }, .brk = { 0 } }, /* 074 */ + { .mk = { 0 }, .brk = { 0 } }, /* 075 */ + { .mk = { 0 }, .brk = { 0 } }, /* 076 */ + { .mk = { 0 }, .brk = { 0 } }, /* 077 */ + { .mk = { 0 }, .brk = { 0 } }, /* 078 */ + { .mk = { 0 }, .brk = { 0 } }, /* 079 */ + { .mk = { 0 }, .brk = { 0 } }, /* 07a */ + { .mk = { 0 }, .brk = { 0 } }, /* 07b */ + { .mk = { 0 }, .brk = { 0 } }, /* 07c */ + { .mk = { 0 }, .brk = { 0 } }, /* 07d */ + { .mk = { 0 }, .brk = { 0 } }, /* 07e */ + { .mk = { 0 }, .brk = { 0 } }, /* 07f */ + { .mk = { 0 }, .brk = { 0 } }, /* 080 */ + { .mk = { 0 }, .brk = { 0 } }, /* 081 */ + { .mk = { 0 }, .brk = { 0 } }, /* 082 */ + { .mk = { 0 }, .brk = { 0 } }, /* 083 */ + { .mk = { 0 }, .brk = { 0 } }, /* 084 */ + { .mk = { 0 }, .brk = { 0 } }, /* 085 */ + { .mk = { 0 }, .brk = { 0 } }, /* 086 */ + { .mk = { 0 }, .brk = { 0 } }, /* 087 */ + { .mk = { 0 }, .brk = { 0 } }, /* 088 */ + { .mk = { 0 }, .brk = { 0 } }, /* 089 */ + { .mk = { 0 }, .brk = { 0 } }, /* 08a */ + { .mk = { 0 }, .brk = { 0 } }, /* 08b */ + { .mk = { 0 }, .brk = { 0 } }, /* 08c */ + { .mk = { 0 }, .brk = { 0 } }, /* 08d */ + { .mk = { 0 }, .brk = { 0 } }, /* 08e */ + { .mk = { 0 }, .brk = { 0 } }, /* 08f */ + { .mk = { 0 }, .brk = { 0 } }, /* 090 */ + { .mk = { 0 }, .brk = { 0 } }, /* 091 */ + { .mk = { 0 }, .brk = { 0 } }, /* 092 */ + { .mk = { 0 }, .brk = { 0 } }, /* 093 */ + { .mk = { 0 }, .brk = { 0 } }, /* 094 */ + { .mk = { 0 }, .brk = { 0 } }, /* 095 */ + { .mk = { 0 }, .brk = { 0 } }, /* 096 */ + { .mk = { 0 }, .brk = { 0 } }, /* 097 */ + { .mk = { 0 }, .brk = { 0 } }, /* 098 */ + { .mk = { 0 }, .brk = { 0 } }, /* 099 */ + { .mk = { 0 }, .brk = { 0 } }, /* 09a */ + { .mk = { 0 }, .brk = { 0 } }, /* 09b */ + { .mk = { 0 }, .brk = { 0 } }, /* 09c */ + { .mk = { 0 }, .brk = { 0 } }, /* 09d */ + { .mk = { 0 }, .brk = { 0 } }, /* 09e */ + { .mk = { 0 }, .brk = { 0 } }, /* 09f */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 0af */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0be */ + { .mk = { 0 }, .brk = { 0 } }, /* 0bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 0cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0da */ + { .mk = { 0 }, .brk = { 0 } }, /* 0db */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0de */ + { .mk = { 0 }, .brk = { 0 } }, /* 0df */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 0eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 0fe */ + { .mk = { 0 }, .brk = { 0 } }, /* 0ff */ + { .mk = { 0 }, .brk = { 0 } }, /* 100 */ + { .mk = { 0 }, .brk = { 0 } }, /* 101 */ + { .mk = { 0 }, .brk = { 0 } }, /* 102 */ + { .mk = { 0 }, .brk = { 0 } }, /* 103 */ + { .mk = { 0 }, .brk = { 0 } }, /* 104 */ + { .mk = { 0 }, .brk = { 0 } }, /* 105 */ + { .mk = { 0 }, .brk = { 0 } }, /* 106 */ + { .mk = { 0 }, .brk = { 0 } }, /* 107 */ + { .mk = { 0 }, .brk = { 0 } }, /* 108 */ + { .mk = { 0 }, .brk = { 0 } }, /* 109 */ + { .mk = { 0 }, .brk = { 0 } }, /* 10a */ + { .mk = { 0 }, .brk = { 0 } }, /* 10b */ + { .mk = { 0 }, .brk = { 0 } }, /* 10c */ + { .mk = { 0 }, .brk = { 0 } }, /* 10d */ + { .mk = { 0 }, .brk = { 0 } }, /* 10e */ + { .mk = { 0 }, .brk = { 0 } }, /* 10f */ + { .mk = { 0 }, .brk = { 0 } }, /* 110 */ + { .mk = { 0 }, .brk = { 0 } }, /* 111 */ + { .mk = { 0 }, .brk = { 0 } }, /* 112 */ + { .mk = { 0 }, .brk = { 0 } }, /* 113 */ + { .mk = { 0 }, .brk = { 0 } }, /* 114 */ + { .mk = { 0 }, .brk = { 0 } }, /* 115 */ + { .mk = { 0 }, .brk = { 0 } }, /* 116 */ + { .mk = { 0 }, .brk = { 0 } }, /* 117 */ + { .mk = { 0 }, .brk = { 0 } }, /* 118 */ + { .mk = { 0 }, .brk = { 0 } }, /* 119 */ + { .mk = { 0 }, .brk = { 0 } }, /* 11a */ + { .mk = { 0 }, .brk = { 0 } }, /* 11b */ + { .mk = { 0x1c, 0 }, .brk = { 0x9c, 0 } }, /* 11c */ + { .mk = { 0x1d, 0 }, .brk = { 0x9d, 0 } }, /* 11d */ + { .mk = { 0 }, .brk = { 0 } }, /* 11e */ + { .mk = { 0 }, .brk = { 0 } }, /* 11f */ + { .mk = { 0 }, .brk = { 0 } }, /* 120 */ + { .mk = { 0 }, .brk = { 0 } }, /* 121 */ + { .mk = { 0 }, .brk = { 0 } }, /* 122 */ + { .mk = { 0 }, .brk = { 0 } }, /* 123 */ + { .mk = { 0 }, .brk = { 0 } }, /* 124 */ + { .mk = { 0 }, .brk = { 0 } }, /* 125 */ + { .mk = { 0 }, .brk = { 0 } }, /* 126 */ + { .mk = { 0 }, .brk = { 0 } }, /* 127 */ + { .mk = { 0 }, .brk = { 0 } }, /* 128 */ + { .mk = { 0 }, .brk = { 0 } }, /* 129 */ + { .mk = { 0 }, .brk = { 0 } }, /* 12a */ + { .mk = { 0 }, .brk = { 0 } }, /* 12b */ + { .mk = { 0 }, .brk = { 0 } }, /* 12c */ + { .mk = { 0 }, .brk = { 0 } }, /* 12d */ + { .mk = { 0 }, .brk = { 0 } }, /* 12e */ + { .mk = { 0 }, .brk = { 0 } }, /* 12f */ + { .mk = { 0 }, .brk = { 0 } }, /* 130 */ + { .mk = { 0 }, .brk = { 0 } }, /* 131 */ + { .mk = { 0 }, .brk = { 0 } }, /* 132 */ + { .mk = { 0 }, .brk = { 0 } }, /* 133 */ + { .mk = { 0 }, .brk = { 0 } }, /* 134 */ + { .mk = { 0x35, 0 }, .brk = { 0xb5, 0 } }, /* 135 */ + { .mk = { 0 }, .brk = { 0 } }, /* 136 */ + { .mk = { 0x37, 0 }, .brk = { 0xb7, 0 } }, /* 137 */ + { .mk = { 0x38, 0 }, .brk = { 0xb8, 0 } }, /* 138 */ + { .mk = { 0 }, .brk = { 0 } }, /* 139 */ + { .mk = { 0 }, .brk = { 0 } }, /* 13a */ + { .mk = { 0 }, .brk = { 0 } }, /* 13b */ + { .mk = { 0 }, .brk = { 0 } }, /* 13c */ + { .mk = { 0 }, .brk = { 0 } }, /* 13d */ + { .mk = { 0 }, .brk = { 0 } }, /* 13e */ + { .mk = { 0 }, .brk = { 0 } }, /* 13f */ + { .mk = { 0 }, .brk = { 0 } }, /* 140 */ + { .mk = { 0 }, .brk = { 0 } }, /* 141 */ + { .mk = { 0 }, .brk = { 0 } }, /* 142 */ + { .mk = { 0 }, .brk = { 0 } }, /* 143 */ + { .mk = { 0 }, .brk = { 0 } }, /* 144 */ + { .mk = { 0 }, .brk = { 0 } }, /* 145 */ + { .mk = { 0x46, 0 }, .brk = { 0xc6, 0 } }, /* 146 */ + { .mk = { 0x47, 0 }, .brk = { 0xc7, 0 } }, /* 147 */ + { .mk = { 0x48, 0 }, .brk = { 0xc8, 0 } }, /* 148 */ + { .mk = { 0x49, 0 }, .brk = { 0xc9, 0 } }, /* 149 */ + { .mk = { 0 }, .brk = { 0 } }, /* 14a */ + { .mk = { 0x4b, 0 }, .brk = { 0xcb, 0 } }, /* 14b */ + { .mk = { 0 }, .brk = { 0 } }, /* 14c */ + { .mk = { 0x4d, 0 }, .brk = { 0xcd, 0 } }, /* 14d */ + { .mk = { 0 }, .brk = { 0 } }, /* 14e */ + { .mk = { 0x4f, 0 }, .brk = { 0xcf, 0 } }, /* 14f */ + { .mk = { 0x50, 0 }, .brk = { 0xd0, 0 } }, /* 150 */ + { .mk = { 0x51, 0 }, .brk = { 0xd1, 0 } }, /* 151 */ + { .mk = { 0x52, 0 }, .brk = { 0xd2, 0 } }, /* 152 */ + { .mk = { 0x53, 0 }, .brk = { 0xd3, 0 } }, /* 153 */ + { .mk = { 0 }, .brk = { 0 } }, /* 154 */ + { .mk = { 0 }, .brk = { 0 } }, /* 155 */ + { .mk = { 0 }, .brk = { 0 } }, /* 156 */ + { .mk = { 0 }, .brk = { 0 } }, /* 157 */ + { .mk = { 0 }, .brk = { 0 } }, /* 158 */ + { .mk = { 0 }, .brk = { 0 } }, /* 159 */ + { .mk = { 0 }, .brk = { 0 } }, /* 15a */ + { .mk = { 0 }, .brk = { 0 } }, /* 15b */ + { .mk = { 0 }, .brk = { 0 } }, /* 15c */ + { .mk = { 0x54, 0 }, .brk = { 0xd4, 0 } }, /* 15d */ + { .mk = { 0x56, 0 }, .brk = { 0xd6, 0 } }, /* 15e */ + { .mk = { 0x5c, 0 }, .brk = { 0xdc, 0 } }, /* 15f */ + { .mk = { 0 }, .brk = { 0 } }, /* 160 */ + { .mk = { 0 }, .brk = { 0 } }, /* 161 */ + { .mk = { 0 }, .brk = { 0 } }, /* 162 */ + { .mk = { 0 }, .brk = { 0 } }, /* 163 */ + { .mk = { 0 }, .brk = { 0 } }, /* 164 */ + { .mk = { 0 }, .brk = { 0 } }, /* 165 */ + { .mk = { 0 }, .brk = { 0 } }, /* 166 */ + { .mk = { 0 }, .brk = { 0 } }, /* 167 */ + { .mk = { 0 }, .brk = { 0 } }, /* 168 */ + { .mk = { 0 }, .brk = { 0 } }, /* 169 */ + { .mk = { 0 }, .brk = { 0 } }, /* 16a */ + { .mk = { 0 }, .brk = { 0 } }, /* 16b */ + { .mk = { 0 }, .brk = { 0 } }, /* 16c */ + { .mk = { 0 }, .brk = { 0 } }, /* 16d */ + { .mk = { 0 }, .brk = { 0 } }, /* 16e */ + { .mk = { 0 }, .brk = { 0 } }, /* 16f */ + { .mk = { 0 }, .brk = { 0 } }, /* 170 */ + { .mk = { 0 }, .brk = { 0 } }, /* 171 */ + { .mk = { 0 }, .brk = { 0 } }, /* 172 */ + { .mk = { 0 }, .brk = { 0 } }, /* 173 */ + { .mk = { 0 }, .brk = { 0 } }, /* 174 */ + { .mk = { 0 }, .brk = { 0 } }, /* 175 */ + { .mk = { 0 }, .brk = { 0 } }, /* 176 */ + { .mk = { 0 }, .brk = { 0 } }, /* 177 */ + { .mk = { 0 }, .brk = { 0 } }, /* 178 */ + { .mk = { 0 }, .brk = { 0 } }, /* 179 */ + { .mk = { 0 }, .brk = { 0 } }, /* 17a */ + { .mk = { 0 }, .brk = { 0 } }, /* 17b */ + { .mk = { 0 }, .brk = { 0 } }, /* 17c */ + { .mk = { 0 }, .brk = { 0 } }, /* 17d */ + { .mk = { 0 }, .brk = { 0 } }, /* 17e */ + { .mk = { 0 }, .brk = { 0 } }, /* 17f */ + { .mk = { 0 }, .brk = { 0 } }, /* 180 */ + { .mk = { 0 }, .brk = { 0 } }, /* 181 */ + { .mk = { 0 }, .brk = { 0 } }, /* 182 */ + { .mk = { 0 }, .brk = { 0 } }, /* 183 */ + { .mk = { 0 }, .brk = { 0 } }, /* 184 */ + { .mk = { 0 }, .brk = { 0 } }, /* 185 */ + { .mk = { 0 }, .brk = { 0 } }, /* 186 */ + { .mk = { 0 }, .brk = { 0 } }, /* 187 */ + { .mk = { 0 }, .brk = { 0 } }, /* 188 */ + { .mk = { 0 }, .brk = { 0 } }, /* 189 */ + { .mk = { 0 }, .brk = { 0 } }, /* 18a */ + { .mk = { 0 }, .brk = { 0 } }, /* 18b */ + { .mk = { 0 }, .brk = { 0 } }, /* 18c */ + { .mk = { 0 }, .brk = { 0 } }, /* 18d */ + { .mk = { 0 }, .brk = { 0 } }, /* 18e */ + { .mk = { 0 }, .brk = { 0 } }, /* 18f */ + { .mk = { 0 }, .brk = { 0 } }, /* 190 */ + { .mk = { 0 }, .brk = { 0 } }, /* 191 */ + { .mk = { 0 }, .brk = { 0 } }, /* 192 */ + { .mk = { 0 }, .brk = { 0 } }, /* 193 */ + { .mk = { 0 }, .brk = { 0 } }, /* 194 */ + { .mk = { 0 }, .brk = { 0 } }, /* 195 */ + { .mk = { 0 }, .brk = { 0 } }, /* 196 */ + { .mk = { 0 }, .brk = { 0 } }, /* 197 */ + { .mk = { 0 }, .brk = { 0 } }, /* 198 */ + { .mk = { 0 }, .brk = { 0 } }, /* 199 */ + { .mk = { 0 }, .brk = { 0 } }, /* 19a */ + { .mk = { 0 }, .brk = { 0 } }, /* 19b */ + { .mk = { 0 }, .brk = { 0 } }, /* 19c */ + { .mk = { 0 }, .brk = { 0 } }, /* 19d */ + { .mk = { 0 }, .brk = { 0 } }, /* 19e */ + { .mk = { 0 }, .brk = { 0 } }, /* 19f */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1a9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1aa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ab */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ac */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ad */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ae */ + { .mk = { 0 }, .brk = { 0 } }, /* 1af */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1b9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ba */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1be */ + { .mk = { 0 }, .brk = { 0 } }, /* 1bf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1c9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ca */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ce */ + { .mk = { 0 }, .brk = { 0 } }, /* 1cf */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1d9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1da */ + { .mk = { 0 }, .brk = { 0 } }, /* 1db */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1dd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1de */ + { .mk = { 0 }, .brk = { 0 } }, /* 1df */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1e9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ea */ + { .mk = { 0 }, .brk = { 0 } }, /* 1eb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ec */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ed */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ee */ + { .mk = { 0 }, .brk = { 0 } }, /* 1ef */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f0 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f1 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f2 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f3 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f4 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f5 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f6 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f7 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f8 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1f9 */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fa */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fb */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fc */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fd */ + { .mk = { 0 }, .brk = { 0 } }, /* 1fe */ + { .mk = { 0 }, .brk = { 0 } } /* 1ff */ // clang-format on }; @@ -1526,6 +2038,8 @@ m19_vid_init(m19_vid_t *vid) vid->ogc.mono_display = 0; else vid->ogc.mono_display = 1; + + vid->ogc.ctrl_addr = 0x3db; /* OGC emulation part end */ /* Plantronics emulation part begin*/ @@ -1707,7 +2221,7 @@ m24_read(uint16_t port, UNUSED(void *priv)) "Reserved for HDU", same as for Switch 3 */ /* Switch 3 - Disable internal BIOS HD */ - if (hdc_current != HDC_INTERNAL) + if (hdc_current[0] != HDC_INTERNAL) ret |= 0x4; /* Switch 2 - Set fast startup */ @@ -1805,7 +2319,7 @@ machine_xt_m24_init(const machine_t *model) machine_common_init(model); /* On-board FDC can be disabled only on M24SP */ - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); /* Address 66-67 = mainboard dip-switch settings */ @@ -1837,7 +2351,7 @@ machine_xt_m24_init(const machine_t *model) m24_kbd_init(m24_kbd); device_add_ex(&m24_kbd_device, m24_kbd); - if (hdc_current == HDC_INTERNAL) + if (hdc_current[0] == HDC_INTERNAL) device_add(&st506_xt_wd1002a_wx1_nobios_device); return ret; @@ -1881,7 +2395,7 @@ machine_xt_m240_init(const machine_t *model) m24_kbd_init(m24_kbd); device_add_ex(&m24_kbd_device, m24_kbd); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); /* io.c logs clearly show it using port 3F7 */ if (joystick_type) @@ -1897,7 +2411,7 @@ machine_xt_m240_init(const machine_t *model) mm58274_init(nvr, model->nvrmask + 1); - if (hdc_current == HDC_INTERNAL) + if (hdc_current[0] == HDC_INTERNAL) device_add(&st506_xt_wd1002a_wx1_nobios_device); return ret; diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index a12fa4e96b..5a787292fa 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -969,7 +969,7 @@ machine_xt_t1200_init(const machine_t *model) if (gfxcard[0] == VID_INTERNAL) device_add(&t1200_video_device); - if (hdc_current <= 1) + if (hdc_current[0] <= HDC_INTERNAL) device_add(&st506_xt_toshiba_t1200_device); return ret; diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index 3f07e6a4e7..8515ea27ab 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -201,7 +201,7 @@ machine_xt_xi8088_init(const machine_t *model) machine_common_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_at_device); device_add(&keyboard_ps2_xi8088_device); diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 0da0919175..f5e2317724 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -140,7 +140,7 @@ machine_xt_z184_init(const machine_t *model) machine_zenith_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_device); lpt1_remove(); /* only one parallel port */ @@ -170,7 +170,7 @@ machine_xt_z151_init(const machine_t *model) machine_zenith_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_tandy_device); return ret; @@ -193,7 +193,7 @@ machine_xt_z159_init(const machine_t *model) machine_zenith_init(model); - if (fdc_type == FDC_INTERNAL) + if (fdc_current[0] == FDC_INTERNAL) device_add(&fdc_xt_tandy_device); /* parallel port is on the memory board */ diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 8474152898..0a919e799e 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -57,30 +57,30 @@ extern const device_t compaq_plasma_device; extern const device_t ps1_2011_device; const machine_filter_t machine_types[] = { - { "None", MACHINE_TYPE_NONE }, - { "8088", MACHINE_TYPE_8088 }, - { "8086", MACHINE_TYPE_8086 }, - { "80286", MACHINE_TYPE_286 }, - { "i386SX", MACHINE_TYPE_386SX }, - { "486SLC", MACHINE_TYPE_486SLC }, - { "i386DX", MACHINE_TYPE_386DX }, - { "i386DX/i486", MACHINE_TYPE_386DX_486 }, - { "i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, - { "i486 (Socket 2)", MACHINE_TYPE_486_S2 }, - { "i486 (Socket 3)", MACHINE_TYPE_486_S3 }, - { "i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, - { "Socket 4", MACHINE_TYPE_SOCKET4 }, - { "Socket 5", MACHINE_TYPE_SOCKET5 }, - { "Socket 7 (Single Voltage)", MACHINE_TYPE_SOCKET7_3V }, - { "Socket 7 (Dual Voltage)", MACHINE_TYPE_SOCKET7 }, - { "Super Socket 7", MACHINE_TYPE_SOCKETS7 }, - { "Socket 8", MACHINE_TYPE_SOCKET8 }, - { "Slot 1", MACHINE_TYPE_SLOT1 }, - { "Slot 1/2", MACHINE_TYPE_SLOT1_2 }, - { "Slot 1/Socket 370", MACHINE_TYPE_SLOT1_370 }, - { "Slot 2", MACHINE_TYPE_SLOT2 }, - { "Socket 370", MACHINE_TYPE_SOCKET370 }, - { "Miscellaneous", MACHINE_TYPE_MISC } + { "None", MACHINE_TYPE_NONE }, + { "[1979] 8088", MACHINE_TYPE_8088 }, + { "[1978] 8086", MACHINE_TYPE_8086 }, + { "[1982] 80286", MACHINE_TYPE_286 }, + { "[1988] i386SX", MACHINE_TYPE_386SX }, + { "[1992] 486SLC", MACHINE_TYPE_486SLC }, + { "[1985] i386DX", MACHINE_TYPE_386DX }, + { "[1989] i386DX/i486", MACHINE_TYPE_386DX_486 }, + { "[1992] i486 (Socket 168 and 1)", MACHINE_TYPE_486 }, + { "[1992] i486 (Socket 2)", MACHINE_TYPE_486_S2 }, + { "[1994] i486 (Socket 3)", MACHINE_TYPE_486_S3 }, + { "[1992] i486 (Miscellaneous)", MACHINE_TYPE_486_MISC }, + { "[1993] Socket 4", MACHINE_TYPE_SOCKET4 }, + { "[1994] Socket 5", MACHINE_TYPE_SOCKET5 }, + { "[1995] Socket 7 (Single Voltage)", MACHINE_TYPE_SOCKET7_3V }, + { "[1996] Socket 7 (Dual Voltage)", MACHINE_TYPE_SOCKET7 }, + { "[1998] Super Socket 7", MACHINE_TYPE_SOCKETS7 }, + { "[1995] Socket 8", MACHINE_TYPE_SOCKET8 }, + { "[1997] Slot 1", MACHINE_TYPE_SLOT1 }, + { "[1998] Slot 1/2", MACHINE_TYPE_SLOT1_2 }, + { "[1998] Slot 1/Socket 370", MACHINE_TYPE_SLOT1_370 }, + { "[1998] Slot 2", MACHINE_TYPE_SLOT2 }, + { "[1998] Socket 370", MACHINE_TYPE_SOCKET370 }, + { "Miscellaneous", MACHINE_TYPE_MISC } }; const machine_filter_t machine_chipsets[] = { @@ -126,6 +126,9 @@ const machine_filter_t machine_chipsets[] = { { "Intel 440GX", MACHINE_CHIPSET_INTEL_440GX }, { "OPTi 283", MACHINE_CHIPSET_OPTI_283 }, { "OPTi 291", MACHINE_CHIPSET_OPTI_291 }, + { "OPTi 381", MACHINE_CHIPSET_OPTI_381 }, + { "OPTi 391", MACHINE_CHIPSET_OPTI_391 }, + { "OPTi 481", MACHINE_CHIPSET_OPTI_481 }, { "OPTi 493", MACHINE_CHIPSET_OPTI_493 }, { "OPTi 495", MACHINE_CHIPSET_OPTI_495 }, { "OPTi 499", MACHINE_CHIPSET_OPTI_499 }, @@ -1339,6 +1342,45 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + { + .name = "[8088] Pravetz 16S / CPU12 Plus", + .internal_name = "pravetz16s", + .type = MACHINE_TYPE_8088, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_xt_pravetz16s_cpu12p_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_8088, + .block = CPU_BLOCK_NONE, + .min_bus = 4772728, + .max_bus = 12000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PC, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 512, + .max = 1024, + .step = 128 + }, + .nvrmask = 0, + .kbc_device = &keyboard_xt_device, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, { .name = "[8088] Sanyo SX-16", .internal_name = "sansx16", @@ -1457,17 +1499,17 @@ const machine_t machines[] = { .net_device = NULL }, { - .name = "[8088] Tandy 1000", + .name = "[8088] Tandy 1000 SX", .internal_name = "tandy", .type = MACHINE_TYPE_8088, .chipset = MACHINE_CHIPSET_PROPRIETARY, - .init = machine_tandy_init, + .init = machine_tandy1000sx_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_8088_EUROPC, + .package = CPU_PKG_8088, .block = CPU_BLOCK_NONE, .min_bus = 0, .max_bus = 0, @@ -1479,7 +1521,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_PC, .flags = MACHINE_VIDEO_FIXED, .ram = { - .min = 128, + .min = 384, .max = 640, .step = 128 }, @@ -1506,7 +1548,7 @@ const machine_t machines[] = { .available_flag = MACHINE_AVAILABLE, .gpio_acpi_handler = NULL, .cpu = { - .package = CPU_PKG_8088_EUROPC, + .package = CPU_PKG_8088, .block = CPU_BLOCK_NONE, .min_bus = 0, .max_bus = 0, @@ -1518,7 +1560,7 @@ const machine_t machines[] = { .bus_flags = MACHINE_PC, .flags = MACHINE_VIDEO_FIXED, .ram = { - .min = 384, + .min = 256, .max = 640, .step = 128 }, @@ -1612,7 +1654,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) +#ifdef USE_LASERXT { .name = "[8088] VTech Laser Turbo XT", .internal_name = "ltxt", @@ -1652,7 +1694,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* defined(DEV_BRANCH) && defined(USE_LASERXT) */ +#endif /* USE_LASERXT */ /* Has a standard PS/2 KBC (so, use IBM PS/2 Type 1). */ { .name = "[8088] Xi8088", @@ -2477,7 +2519,7 @@ const machine_t machines[] = { .net_device = NULL }, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) +#ifdef USE_LASERXT { .name = "[8086] VTech Laser XT3", .internal_name = "lxt3", @@ -2517,7 +2559,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* defined(DEV_BRANCH) && defined(USE_LASERXT) */ +#endif /* USE_LASERXT */ /* 286 AT machines */ /* Has IBM AT KBC firmware. */ @@ -2545,8 +2587,8 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 256, - .max = 15872, - .step = 128 + .max = 512, + .step = 256 }, .nvrmask = 63, .kbc_device = NULL, @@ -2665,7 +2707,7 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 256, - .max = 15872, + .max = 640, .step = 128 }, .nvrmask = 127, @@ -2705,8 +2747,8 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 256, - .max = 15872, - .step = 128 + .max = 512, + .step = 256 }, .nvrmask = 63, .kbc_device = NULL, @@ -2921,7 +2963,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#if defined(DEV_BRANCH) && defined(USE_OLIVETTI) + /* Has Chips & Technologies KBC firmware. */ + { + .name = "[ISA] Wells American A*Star", + .internal_name = "wellamerastar", + .type = MACHINE_TYPE_286, + .chipset = MACHINE_CHIPSET_DISCRETE, + .init = machine_at_wellamerastar_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_286, + .block = CPU_BLOCK_NONE, + .min_bus = 6000000, + .max_bus = 14000000, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 512, + .max = 1024, + .step = 512 + }, + .nvrmask = 63, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, +#ifdef USE_OLIVETTI /* Has Olivetti KBC firmware. */ { .name = "[ISA] Olivetti M290", @@ -2962,8 +3044,8 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* defined(DEV_BRANCH) && defined(USE_OLIVETTI) */ -#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) +#endif /* USE_OLIVETTI */ +#ifdef USE_OPEN_AT /* Has IBM AT KBC firmware. */ { .name = "[ISA] OpenAT", @@ -3004,7 +3086,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* defined(DEV_BRANCH) && defined(USE_OPEN_AT) */ +#endif /* USE_OPEN_AT */ /* Has IBM AT KBC firmware. */ { .name = "[ISA] Phoenix IBM AT", @@ -3030,8 +3112,8 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 256, - .max = 15872, - .step = 128 + .max = 512, + .step = 256 }, .nvrmask = 63, .kbc_device = NULL, @@ -3070,8 +3152,8 @@ const machine_t machines[] = { .flags = MACHINE_FLAGS_NONE, .ram = { .min = 256, - .max = 15872, - .step = 128 + .max = 512, + .step = 256 }, .nvrmask = 63, .kbc_device = NULL, @@ -4168,6 +4250,46 @@ const machine_t machines[] = { .vid_device = NULL, .snd_device = NULL, .net_device = NULL + }, + { + .name = "[ALI M1409] Acer 100T", + .internal_name = "acer100t", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1409, + .init = machine_at_acer100t_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .block = CPU_BLOCK_NONE, + .min_bus = 16000000, + .max_bus = 25000000, /* Limited to 25 due a inaccurate cpu speed */ + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0, + + }, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO , /* Machine has internal OTI 077 Video card*/ + .ram = { + .min = 2048, + .max = 16256, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &oti077_acer100t_device, + .snd_device = NULL, + .net_device = NULL }, /* Has IBM PS/2 Type 1 KBC firmware. */ { @@ -5182,7 +5304,47 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The board has a "ASII KB-100" which I was not able to find any information about, + /* Has AMIKey 'F' KBC firmware. */ + { + .name = "[OPTi 391] DataExpert 386WB", + .internal_name = "dataexpert386wb", + .type = MACHINE_TYPE_386DX, + .chipset = MACHINE_CHIPSET_OPTI_391, + .init = machine_at_dataexpert386wb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386DX, /* Actual machine only supports 386DXes */ + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_FLAGS_NONE, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* The board has a "ASII KB-100" which I was not able to find any information about, but the BIOS sends commands C9 without a parameter and D5, both of which are Phoenix MultiKey commands. */ { @@ -5510,17 +5672,13 @@ const machine_t machines[] = { }, /* 486 machines - Socket 1 */ - /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. - It also has those Ex commands also seen on the VIA VT82C42N (the BIOS - supposedly sends command EF. - The board was also seen in 2003 with a -H string - perhaps someone swapped - the KBC? */ + /* Has AMI KF KBC firmware. */ { - .name = "[ALi M1429] Olystar LIL1429", - .internal_name = "ali1429", + .name = "[ZyMOS Poach] Genoa Unknown 486", + .internal_name = "genoa486", .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_ALI_M1429, - .init = machine_at_ali1429_init, + .chipset = MACHINE_CHIPSET_ZYMOS_POACH, + .init = machine_at_genoa486_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -5535,11 +5693,51 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_VLB, + .bus_flags = MACHINE_AT, .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 32768, + .max = 16384, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, + /* Has AMI KF KBC firmware. */ + { + .name = "[OPTi 381] Gigabyte GA-486L", + .internal_name = "ga486l", + .type = MACHINE_TYPE_486, + .chipset = MACHINE_CHIPSET_OPTI_381, + .init = machine_at_ga486l_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET1, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_AT, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 16384, .step = 1024 }, .nvrmask = 127, @@ -5758,13 +5956,16 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ + /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends + commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, + but it does not write a byte after C9, which is consistent with AMIKey, so + this must have some form of AMIKey. */ { - .name = "[SiS 461] Acer V10", - .internal_name = "acerv10", + .name = "[VIA VT82C495] FIC 486-VC-HD", + .internal_name = "486vchd", .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_SIS_461, - .init = machine_at_acerv10_init, + .chipset = MACHINE_CHIPSET_VIA_VT82C495, + .init = machine_at_486vchd_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -5779,11 +5980,11 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_PS2_VLB, - .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal SCSI: Adaptec AIC-6360 */ + .bus_flags = MACHINE_AT, + .flags = MACHINE_APM, .ram = { .min = 1024, - .max = 32768, + .max = 64512, .step = 1024 }, .nvrmask = 127, @@ -5798,13 +5999,13 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* Has MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ + /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ { - .name = "[SiS 471] SiS VL-BUS 471 REV. A1", - .internal_name = "px471", + .name = "[VLSI 82C480] HP Vectra 486VL", + .internal_name = "vect486vl", .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_SIS_471, - .init = machine_at_px471_init, + .chipset = MACHINE_CHIPSET_VLSI_VL82C480, + .init = machine_at_vect486vl_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -5819,12 +6020,12 @@ const machine_t machines[] = { .min_multi = 0, .max_multi = 0 }, - .bus_flags = MACHINE_VLB, - .flags = MACHINE_IDE | MACHINE_APM, + .bus_flags = MACHINE_PS2, + .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, .ram = { - .min = 1024, - .max = 131072, - .step = 1024 + .min = 2048, + .max = 32768, + .step = 2048 }, .nvrmask = 127, .kbc_device = NULL, @@ -5833,91 +6034,8 @@ const machine_t machines[] = { .gpio_acpi = 0xffffffff, .device = NULL, .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, - /* The chip is a Lance LT38C41, a clone of the Intel 8041, and the BIOS sends - commands BC, BD, and C9 which exist on both AMIKey and Phoenix MultiKey/42, - but it does not write a byte after C9, which is consistent with AMIKey, so - this must have some form of AMIKey. */ - { - .name = "[VIA VT82C495] FIC 486-VC-HD", - .internal_name = "486vchd", - .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_VIA_VT82C495, - .init = machine_at_486vchd_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET1, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_AT, - .flags = MACHINE_APM, - .ram = { - .min = 1024, - .max = 64512, - .step = 1024 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, - /* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */ - { - .name = "[VLSI 82C480] HP Vectra 486VL", - .internal_name = "vect486vl", - .type = MACHINE_TYPE_486, - .chipset = MACHINE_CHIPSET_VLSI_VL82C480, - .init = machine_at_vect486vl_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET1, - .block = CPU_BLOCK_NONE, - .min_bus = 0, - .max_bus = 0, - .min_voltage = 0, - .max_voltage = 0, - .min_multi = 0, - .max_multi = 0 - }, - .bus_flags = MACHINE_PS2, - .flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM, - .ram = { - .min = 2048, - .max = 32768, - .step = 2048 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ - .vid_device = &gd5428_onboard_device, + .sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/ + .vid_device = &gd5428_onboard_device, .snd_device = NULL, .net_device = NULL }, @@ -6124,6 +6242,50 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has JetKey 5 KBC Firmware which looks like it is a clone of AMIKey type F. + It also has those Ex commands also seen on the VIA VT82C42N (the BIOS + supposedly sends command EF. + The board was also seen in 2003 with a -H string - perhaps someone swapped + the KBC? */ + { + .name = "[ALi M1429] Olystar LIL1429", + .internal_name = "ali1429", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_ALI_M1429, + .init = machine_at_ali1429_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a standalone AMI Megakey 1993, which is type 'P'. */ { .name = "[IMS 8848] Tekram G486IP", @@ -6164,6 +6326,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMIKey-2 'H' KBC firmware. */ + { + .name = "[OPTi 499] Alaris COUGAR 486BL", + .internal_name = "cougar", + .type = MACHINE_TYPE_486_S2, + .chipset = MACHINE_CHIPSET_OPTI_499, + .init = machine_at_cougar_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3 | CPU_PKG_486BL, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_APM, + .ram = { + .min = 1024, + .max = 65536, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Uses an Intel KBC with Phoenix MultiKey KBC firmware. */ { .name = "[SiS 461] DEC DECpc LPV", @@ -6274,7 +6476,7 @@ const machine_t machines[] = { .step = 1024 }, .nvrmask = 127, - .kbc_device = &keyboard_ps2_ami_device, + .kbc_device = &keyboard_at_ami_device, .kbc_p1 = 0xff, .gpio = 0xffffffff, .gpio_acpi = 0xffffffff, @@ -6529,6 +6731,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Uses an NEC 90M002A (UPD82C42C, 8042 clone) with unknown firmware. */ + { + .name = "[SiS 461] Acer V10", + .internal_name = "acerv10", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_461, + .init = machine_at_acerv10_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_PS2_VLB, + .flags = MACHINE_IDE | MACHINE_APM, /* Machine has internal SCSI: Adaptec AIC-6360 */ + .ram = { + .min = 1024, + .max = 32768, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* The BIOS string ends in -U, unless command 0xA1 (AMIKey get version) returns an 'F', in which case, it ends in -F, so it has an AMIKey F KBC firmware. The photo of the board shows an AMIKey KBC which is indeed F. */ @@ -6731,6 +6973,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has MR (!) KBC firmware, which is a clone of the standard IBM PS/2 KBC firmware. */ + { + .name = "[SiS 471] SiS VL-BUS 471 REV. A1", + .internal_name = "px471", + .type = MACHINE_TYPE_486_S3, + .chipset = MACHINE_CHIPSET_SIS_471, + .init = machine_at_px471_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET3, + .block = CPU_BLOCK_NONE, + .min_bus = 0, + .max_bus = 0, + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0 + }, + .bus_flags = MACHINE_VLB, + .flags = MACHINE_IDE | MACHINE_APM, + .ram = { + .min = 1024, + .max = 131072, + .step = 1024 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* TriGem AMIBIOS Pre-Color with TriGem AMI 'Z' keyboard controller */ { .name = "[SiS 471] TriGem 486G", @@ -10485,14 +10767,15 @@ const machine_t machines[] = { }, /* 430HX */ + /* Has SST Flash. */ /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { - .name = "[i430HX] Acer M3A", - .internal_name = "acerm3a", + .name = "[i430HX] Acer V35N", + .internal_name = "acerv35n", .type = MACHINE_TYPE_SOCKET7_3V, .chipset = MACHINE_CHIPSET_INTEL_430HX, - .init = machine_at_acerm3a_init, + .init = machine_at_acerv35n_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -10502,13 +10785,13 @@ const machine_t machines[] = { .block = CPU_BLOCK_NONE, .min_bus = 50000000, .max_bus = 66666667, - .min_voltage = 3300, + .min_voltage = 3450, .max_voltage = 3520, .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal SCSI */ + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, .ram = { .min = 8192, .max = 196608, @@ -10606,89 +10889,8 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* [TEST] The board doesn't seem to have a KBC at all, which probably means it's an on-chip one on the PC87306 SIO. - A list on a Danish site shows the BIOS as having a -0 string, indicating non-AMI KBC firmware. */ - { - .name = "[i430HX] Supermicro P55T2S", - .internal_name = "p55t2s", - .type = MACHINE_TYPE_SOCKET7_3V, - .chipset = MACHINE_CHIPSET_INTEL_430HX, - .init = machine_at_p55t2s_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 66666667, - .min_voltage = 3300, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 3.0 - }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, - .ram = { - .min = 8192, - .max = 786432, - .step = 8192 - }, - .nvrmask = 255, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, /* 430VX */ - /* Has AMIKey H KBC firmware (AMIKey-2). */ - { - .name = "[i430VX] ECS P5VX-B", - .internal_name = "p5vxb", - .type = MACHINE_TYPE_SOCKET7_3V, - .chipset = MACHINE_CHIPSET_INTEL_430VX, - .init = machine_at_p5vxb_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 66666667, - .min_voltage = 3380, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 3.0 - }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, - .ram = { - .min = 8192, - .max = 131072, - .step = 8192 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, /* Has a SM(S)C FDC37C932FR Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ { @@ -10937,15 +11139,14 @@ const machine_t machines[] = { /* Socket 7 (Dual Voltage) machines */ /* 430HX */ - /* Has SST Flash. */ /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { - .name = "[i430HX] Acer V35N", - .internal_name = "acerv35n", + .name = "[i430HX] Acer M3A", + .internal_name = "acerm3a", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430HX, - .init = machine_at_acerv35n_init, + .init = machine_at_acerm3a_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -10960,8 +11161,8 @@ const machine_t machines[] = { .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_GAMEPORT | MACHINE_USB, /* Machine has internal SCSI */ .ram = { .min = 8192, .max = 196608, @@ -11019,6 +11220,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* The base board has a Holtek HT6542B with the AMIKey-2 (updated 'H') KBC firmware. */ + { + .name = "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", + .internal_name = "p65up5_cp55t2d", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_p65up5_cp55t2d_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Machine has AMB */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, + .ram = { + .min = 8192, + .max = 524288, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a SM(S)C FDC37C935 Super I/O chip with on-chip KBC with Phoenix MultiKey/42 (version 1.38) KBC firmware. */ { @@ -11265,13 +11506,14 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - /* The base board has a Holtek HT6542B with the AMIKey-2 (updated 'H') KBC firmware. */ + /* [TEST] The board doesn't seem to have a KBC at all, which probably means it's an on-chip one on the PC87306 SIO. + A list on a Danish site shows the BIOS as having a -0 string, indicating non-AMI KBC firmware. */ { - .name = "[i430HX] ASUS P/I-P65UP5 (C-P55T2D)", - .internal_name = "p65up5_cp55t2d", + .name = "[i430HX] Supermicro P55T2S", + .internal_name = "p55t2s", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430HX, - .init = machine_at_p65up5_cp55t2d_init, + .init = machine_at_p55t2s_init, .p1_handler = NULL, .gpio_handler = NULL, .available_flag = MACHINE_AVAILABLE, @@ -11281,59 +11523,19 @@ const machine_t machines[] = { .block = CPU_BLOCK_NONE, .min_bus = 50000000, .max_bus = 66666667, - .min_voltage = 2500, + .min_voltage = 2800, .max_voltage = 3520, .min_multi = 1.5, .max_multi = 3.0 }, - .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, /* Machine has AMB */ + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, .ram = { .min = 8192, - .max = 524288, - .step = 8192 - }, - .nvrmask = 127, - .kbc_device = NULL, - .kbc_p1 = 0xff, - .gpio = 0xffffffff, - .gpio_acpi = 0xffffffff, - .device = NULL, - .fdc_device = NULL, - .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, - .net_device = NULL - }, - /* Unknown PS/2 KBC. */ - { - .name = "[i430HX] Radisys EPC-2102", - .internal_name = "epc2102", - .type = MACHINE_TYPE_SOCKET7, - .chipset = MACHINE_CHIPSET_INTEL_430HX, - .init = machine_at_epc2102_init, - .p1_handler = NULL, - .gpio_handler = NULL, - .available_flag = MACHINE_AVAILABLE, - .gpio_acpi_handler = NULL, - .cpu = { - .package = CPU_PKG_SOCKET5_7, - .block = CPU_BLOCK_NONE, - .min_bus = 50000000, - .max_bus = 83333333, - .min_voltage = 2500, - .max_voltage = 3520, - .min_multi = 1.5, - .max_multi = 3.0 - }, - .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM, - .ram = { - .min = 8192, - .max = 262144, + .max = 786432, .step = 8192 }, - .nvrmask = 127, + .nvrmask = 255, .kbc_device = NULL, .kbc_p1 = 0xff, .gpio = 0xffffffff, @@ -11631,6 +11833,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Has AMIKey H KBC firmware (AMIKey-2). */ + { + .name = "[i430VX] ECS P5VX-B", + .internal_name = "p5vxb", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430VX, + .init = machine_at_p5vxb_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 66666667, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, + .ram = { + .min = 8192, + .max = 131072, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* Has a SM(S)C FDC37C932FR Super I/O chip with on-chip KBC with AMI MegaKey (revision '5') KBC firmware. */ { @@ -11837,6 +12079,46 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, + /* Unknown PS/2 KBC. */ + { + .name = "[i430HX] Radisys EPC-2102", + .internal_name = "epc2102", + .type = MACHINE_TYPE_SOCKET7, + .chipset = MACHINE_CHIPSET_INTEL_430HX, + .init = machine_at_epc2102_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_SOCKET5_7, + .block = CPU_BLOCK_NONE, + .min_bus = 50000000, + .max_bus = 83333333, + .min_voltage = 2500, + .max_voltage = 3520, + .min_multi = 1.5, + .max_multi = 3.0 + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE_DUAL | MACHINE_APM, + .ram = { + .min = 8192, + .max = 262144, + .step = 8192 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = NULL, + .snd_device = NULL, + .net_device = NULL + }, /* This has a Holtek KBC and the BIOS does not send a single non-standard KBC command, so it must be an ASIC that clones the standard IBM PS/2 KBC. */ { @@ -11882,7 +12164,7 @@ const machine_t machines[] = { /* 430TX */ /* The BIOS sends KBC command B8, CA, and CB, so it has an AMI KBC firmware. */ { - .name = "[i430TX] ADLink NuPRO-592", + .name = "[i430TX] ADLink NuPRO-591/592", .internal_name = "nupro592", .type = MACHINE_TYPE_SOCKET7, .chipset = MACHINE_CHIPSET_INTEL_430TX, @@ -11902,7 +12184,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCI, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI, /* Has internal video: C&T B69000 */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_VIDEO, .ram = { .min = 8192, .max = 262144, @@ -11916,7 +12198,7 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, + .vid_device = &chips_69000_onboard_device, .snd_device = NULL, .net_device = NULL }, @@ -12000,7 +12282,7 @@ const machine_t machines[] = { .snd_device = &cs4236b_device, .net_device = &pcnet_am79c973_onboard_device }, -#if defined(DEV_BRANCH) && defined(USE_AN430TX) +#ifdef USE_AN430TX /* This has the Phoenix MultiKey KBC firmware. */ { .name = "[i430TX] Intel AN430TX", @@ -12041,7 +12323,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, -#endif /* defined(DEV_BRANCH) && defined(USE_AN430TX) */ +#endif /* USE_AN430TX */ /* This has the AMIKey KBC firmware, which is an updated 'F' type. */ { .name = "[i430TX] Intel YM430TX", @@ -12658,7 +12940,7 @@ const machine_t machines[] = { .snd_device = NULL, .net_device = NULL }, - + /* ALi ALADDiN IV+ */ /* Has the ALi M1543 southbridge with on-chip KBC. */ { @@ -12846,7 +13128,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_PCIONLY | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal video: ATI 3D Rage Pro Turbo AGP and sound: Ensoniq ES1373*/ + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, /* Has internal video: ATI 3D Rage Pro Turbo AGP and sound: Ensoniq ES1373 */ .ram = { .min = 8192, .max = 262144, @@ -12861,7 +13143,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = NULL, + .snd_device = &es1373_onboard_device, .net_device = NULL }, /* Has the ALi M1543C southbridge with on-chip KBC. */ @@ -13051,7 +13333,7 @@ const machine_t machines[] = { .max_multi = 5.5 }, .bus_flags = MACHINE_PS2_A97 | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_GAMEPORT | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -13462,7 +13744,7 @@ const machine_t machines[] = { .max_multi = 3.5 }, .bus_flags = MACHINE_PS2_PCI | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_USB, /* Machine has internal video: S3 ViRGE/DX and sound: Crystal CS4236B */ + .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_SOUND | MACHINE_VIDEO | MACHINE_USB, /* Machine has internal video: S3 ViRGE/DX and sound: Crystal CS4236B */ .ram = { .min = 8192, .max = 131072, @@ -13476,8 +13758,8 @@ const machine_t machines[] = { .device = NULL, .fdc_device = NULL, .sio_device = NULL, - .vid_device = NULL, - .snd_device = NULL, + .vid_device = &s3_virge_325_onboard_pci_device, + .snd_device = &cs4236b_device, .net_device = NULL }, /* According to tests from real hardware: This has AMI MegaKey KBC firmware on the @@ -14248,7 +14530,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1373 */ + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, /* Machine has internal sound: Ensoniq ES1371 */ .ram = { .min = 8192, .max = 1048576, @@ -14347,7 +14629,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = &voodoo_3_2000_agp_onboard_8m_device, - .snd_device = NULL, + .snd_device = &es1373_onboard_device, .net_device = NULL }, /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC @@ -14388,7 +14670,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = &voodoo_3_2000_agp_onboard_8m_device, - .snd_device = NULL, + .snd_device = &es1373_onboard_device, .net_device = NULL }, @@ -14396,7 +14678,7 @@ const machine_t machines[] = { /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { - .name = "[SMSC VictoryBX-66] A-Trend ATC-6310BXII", + .name = "[SMSC VictoryBX-66] A-Trend ATC6310BXII", .internal_name = "atc6310bxii", .type = MACHINE_TYPE_SLOT1, .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, @@ -14597,7 +14879,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &es1371_onboard_device, + .snd_device = &es1373_onboard_device, .net_device = NULL }, @@ -14639,7 +14921,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &es1371_onboard_device, /* ES1373 but we currently don't emulate that. */ + .snd_device = &es1373_onboard_device, .net_device = NULL }, /* Has the SiS (5)600 chipset with on-chip KBC. */ @@ -14752,7 +15034,7 @@ const machine_t machines[] = { .max_multi = 8.0 }, .bus_flags = MACHINE_PS2_AGP | MACHINE_BUS_USB, - .flags = MACHINE_IDE_DUAL | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, + .flags = MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_APM | MACHINE_ACPI | MACHINE_USB, .ram = { .min = 8192, .max = 786432, @@ -14767,7 +15049,7 @@ const machine_t machines[] = { .fdc_device = NULL, .sio_device = NULL, .vid_device = NULL, - .snd_device = &es1371_onboard_device, + .snd_device = &es1373_onboard_device, .net_device = NULL }, /* VIA Apollo Pro */ @@ -15115,7 +15397,7 @@ const machine_t machines[] = { /* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC firmware. */ { - .name = "[SMSC VictoryBX-66] A-Trend ATC-7020BXII", + .name = "[SMSC VictoryBX-66] A-Trend ATC7020BXII", .internal_name = "atc7020bxii", .type = MACHINE_TYPE_SOCKET370, .chipset = MACHINE_CHIPSET_SMSC_VICTORYBX_66, diff --git a/src/mem/CMakeLists.txt b/src/mem/CMakeLists.txt index d3d5d1ce77..0e52beb4e1 100644 --- a/src/mem/CMakeLists.txt +++ b/src/mem/CMakeLists.txt @@ -9,9 +9,21 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(mem OBJECT catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c mmu_2386.c - rom.c row.c smram.c spd.c sst_flash.c) +add_library(mem OBJECT + catalyst_flash.c + i2c_eeprom.c + intel_flash.c + mem.c + mmu_2386.c + rom.c + row.c + smram.c + spd.c + sst_flash.c +) diff --git a/src/mem/mem.c b/src/mem/mem.c index be097b5f3d..57dc31e332 100644 --- a/src/mem/mem.c +++ b/src/mem/mem.c @@ -164,46 +164,6 @@ mem_log(const char *fmt, ...) # define mem_log(fmt, ...) #endif -#ifdef USE_DEBUG_REGS_486 -/* As below, 1 = exec, 4 = read. */ -int read_type = 4; - -/* Set trap for data address breakpoints - 1 = exec, 2 = write, 4 = read. */ -void -mem_debug_check_addr(uint32_t addr, int flags) -{ - uint32_t bp_addr; - uint32_t bp_mask; - uint32_t len_type_pair; - int bp_enabled; - uint8_t match_flags[4] = { 0, 2, 0, 6 }; - - if (cpu_state.abrt || ((flags == 1) && (cpu_state.eflags & RF_FLAG))) - return; - - if (dr[7] & 0x000000ff) for (uint8_t i = 0; i < 4; i++) { - bp_addr = dr[i]; - bp_enabled = (dr[7] >> (i << 1)) & 0x03; - len_type_pair = (dr[7] >> (16 + (i << 2))) & 0x0f; - bp_mask = ~((len_type_pair >> 2) & 0x03); - - if ((flags & match_flags[len_type_pair & 0x03]) && ((bp_addr & bp_mask) == (addr & bp_mask))) { - /* - From the Intel i386 documemntation: - - (Note that the processor sets Bn regardless of whether Gn or - Ln is set. If more than one breakpoint condition occurs at one time and if - the breakpoint trap occurs due to an enabled condition other than n, Bn may - be set, even though neither Gn nor Ln is set.) - */ - dr[6] |= (1 << i); - if (bp_enabled) - trap |= (read_type == 1) ? 8 : 4; - } - } -} -#endif - int mem_addr_is_ram(uint32_t addr) { @@ -265,6 +225,19 @@ flushmmucache(void) #endif } +void +flushmmucache_pc(void) +{ + mmuflush++; + + pccache = (uint32_t) 0xffffffff; + pccache2 = (uint8_t *) 0xffffffff; + +#ifdef USE_DYNAREC + codegen_flush(); +#endif +} + void flushmmucache_nopc(void) { @@ -347,7 +320,7 @@ mmutranslatereal_normal(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -368,7 +341,7 @@ mmutranslatereal_normal(uint32_t addr, int rw) temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -432,7 +405,7 @@ mmutranslatereal_pae(uint32_t addr, int rw) if (temp & 0x80) { /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -453,7 +426,7 @@ mmutranslatereal_pae(uint32_t addr, int rw) addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); temp = rammap64(addr4) & 0x000000ffffffffffULL; temp3 = temp & temp4; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -515,7 +488,7 @@ mmutranslate_noabrt_normal(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (temp & ~0x3fffff) + (addr & 0x3fffff); @@ -524,7 +497,7 @@ mmutranslate_noabrt_normal(uint32_t addr, int rw) temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); @@ -559,7 +532,7 @@ mmutranslate_noabrt_pae(uint32_t addr, int rw) if (temp & 0x80) { /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; @@ -570,7 +543,7 @@ mmutranslate_noabrt_pae(uint32_t addr, int rw) temp3 = temp & temp4; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; @@ -2596,6 +2569,19 @@ mem_mapping_set_handler(mem_mapping_t *map, mem_mapping_recalc(map->base, map->size); } +void +mem_mapping_set_write_handler(mem_mapping_t *map, + void (*write_b)(uint32_t addr, uint8_t val, void *priv), + void (*write_w)(uint32_t addr, uint16_t val, void *priv), + void (*write_l)(uint32_t addr, uint32_t val, void *priv)) +{ + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; + + mem_mapping_recalc(map->base, map->size); +} + void mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) { @@ -2833,8 +2819,8 @@ mem_reset(void) */ if (is286) { if (cpu_16bitbus) { - /* 80286/386SX; maximum address space is 16MB. */ - m = 4096; + /* 80286/386SX; maximum address space is 16MB + 16 MB for EMS. */ + m = 8192; /* ALi M6117; maximum address space is 64MB. */ if (is6117) m <<= 2; @@ -3008,10 +2994,9 @@ umc_smram_recalc(uint32_t start, int set) } void -mem_remap_top(int kb) +mem_remap_top_ex(int kb, uint32_t start) { uint32_t c; - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; int offset; int size = mem_size - 640; int set = 1; @@ -3137,6 +3122,12 @@ mem_remap_top(int kb) flushmmucache(); } +void +mem_remap_top(int kb) +{ + mem_remap_top_ex(kb, (mem_size >= 1024) ? mem_size : 1024); +} + void mem_reset_page_blocks(void) { diff --git a/src/mem/mmu_2386.c b/src/mem/mmu_2386.c index abc34ff968..7418a88d83 100644 --- a/src/mem/mmu_2386.c +++ b/src/mem/mmu_2386.c @@ -198,7 +198,7 @@ mmutranslatereal_2386(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -219,7 +219,7 @@ mmutranslatereal_2386(uint32_t addr, int rw) temp = mem_readl_map((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { cr2 = addr; temp &= 1; if (CPL == 3) @@ -258,7 +258,7 @@ mmutranslate_noabrt_2386(uint32_t addr, int rw) if ((temp & 0x80) && (cr4 & CR4_PSE)) { /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !cpl_override && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (temp & ~0x3fffff) + (addr & 0x3fffff); @@ -267,7 +267,7 @@ mmutranslate_noabrt_2386(uint32_t addr, int rw) temp = mem_readl_map((temp & ~0xfff) + ((addr >> 10) & 0xffc)); temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !cpl_override && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) return 0xffffffffffffffffULL; return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); @@ -278,6 +278,7 @@ readmembl_2386(uint32_t addr) { mem_mapping_t *map; uint64_t a; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); @@ -287,7 +288,7 @@ readmembl_2386(uint32_t addr) high_page = 0; - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_read_2386(addr); addr64 = (uint32_t) a; @@ -308,6 +309,7 @@ writemembl_2386(uint32_t addr, uint8_t val) { mem_mapping_t *map; uint64_t a; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; mem_debug_check_addr(addr, 2); GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); @@ -317,7 +319,7 @@ writemembl_2386(uint32_t addr, uint8_t val) high_page = 0; - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_write_2386(addr); addr64 = (uint32_t) a; @@ -336,12 +338,13 @@ uint8_t readmembl_no_mmut_2386(uint32_t addr, uint32_t a64) { mem_mapping_t *map; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); mem_logical_addr = addr; - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return 0xff; @@ -361,12 +364,13 @@ void writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val) { mem_mapping_t *map; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); mem_logical_addr = addr; - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return; @@ -384,6 +388,7 @@ readmemwl_2386(uint32_t addr) { mem_mapping_t *map; uint64_t a; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; addr64a[0] = addr; addr64a[1] = addr + 1; @@ -399,7 +404,7 @@ readmemwl_2386(uint32_t addr) if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { for (uint8_t i = 0; i < 2; i++) { a = mmutranslate_read_2386(addr + i); addr64a[i] = (uint32_t) a; @@ -414,7 +419,7 @@ readmemwl_2386(uint32_t addr) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_read_2386(addr); addr64a[0] = (uint32_t) a; @@ -442,6 +447,7 @@ writememwl_2386(uint32_t addr, uint16_t val) { mem_mapping_t *map; uint64_t a; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; addr64a[0] = addr; addr64a[1] = addr + 1; @@ -457,7 +463,7 @@ writememwl_2386(uint32_t addr, uint16_t val) if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { for (uint8_t i = 0; i < 2; i++) { /* Do not translate a page that has a valid lookup, as that is by definition valid and the whole purpose of the lookup is to avoid repeat identical translations. */ @@ -479,7 +485,7 @@ writememwl_2386(uint32_t addr, uint16_t val) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_write_2386(addr); addr64a[0] = (uint32_t) a; @@ -508,6 +514,7 @@ uint16_t readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) { mem_mapping_t *map; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); @@ -517,7 +524,7 @@ readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return 0xffff; } @@ -527,7 +534,7 @@ readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return 0xffff; @@ -552,6 +559,7 @@ void writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) { mem_mapping_t *map; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); @@ -561,7 +569,7 @@ writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) if (!cpu_cyrix_alignment || (addr & 7) == 7) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return; } @@ -572,7 +580,7 @@ writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return; @@ -600,6 +608,7 @@ readmemll_2386(uint32_t addr) mem_mapping_t *map; int i; uint64_t a = 0x0000000000000000ULL; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); @@ -615,7 +624,7 @@ readmemll_2386(uint32_t addr) if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { for (i = 0; i < 4; i++) { if (i == 0) { a = mmutranslate_read_2386(addr + i); @@ -644,7 +653,7 @@ readmemll_2386(uint32_t addr) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_read_2386(addr); addr64a[0] = (uint32_t) a; @@ -674,6 +683,7 @@ writememll_2386(uint32_t addr, uint32_t val) mem_mapping_t *map; int i; uint64_t a = 0x0000000000000000ULL; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; for (i = 0; i < 4; i++) { addr64a[i] = (uint64_t) (addr + i); @@ -689,7 +699,7 @@ writememll_2386(uint32_t addr, uint32_t val) if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { for (i = 0; i < 4; i++) { /* Do not translate a page that has a valid lookup, as that is by definition valid and the whole purpose of the lookup is to avoid repeat identical translations. */ @@ -723,7 +733,7 @@ writememll_2386(uint32_t addr, uint32_t val) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_write_2386(addr); addr64a[0] = (uint32_t) a; @@ -758,6 +768,7 @@ uint32_t readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) { mem_mapping_t *map; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); @@ -767,7 +778,7 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return 0xffffffff; } @@ -777,7 +788,7 @@ readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return 0xffffffff; @@ -804,6 +815,7 @@ void writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) { mem_mapping_t *map; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); @@ -813,7 +825,7 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) if ((addr & 3) && (!cpu_cyrix_alignment || (addr & 7) > 4)) cycles -= timing_misaligned; if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return; } @@ -824,7 +836,7 @@ writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { if (cpu_state.abrt || high_page) return; @@ -858,6 +870,7 @@ readmemql_2386(uint32_t addr) mem_mapping_t *map; int i; uint64_t a = 0x0000000000000000ULL; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); @@ -872,7 +885,7 @@ readmemql_2386(uint32_t addr) if (addr & 7) { cycles -= timing_misaligned; if ((addr & 0xfff) > 0xff8) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { for (i = 0; i < 8; i++) { if (i == 0) { a = mmutranslate_read_2386(addr + i); @@ -901,7 +914,7 @@ readmemql_2386(uint32_t addr) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { a = mmutranslate_read_2386(addr); addr64a[0] = (uint32_t) a; @@ -924,6 +937,7 @@ writememql_2386(uint32_t addr, uint64_t val) mem_mapping_t *map; int i; uint64_t a = 0x0000000000000000ULL; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; for (i = 0; i < 8; i++) { addr64a[i] = (uint64_t) (addr + i); @@ -938,7 +952,7 @@ writememql_2386(uint32_t addr, uint64_t val) if (addr & 7) { cycles -= timing_misaligned; if ((addr & 0xfff) > 0xff8) { - if (cr0 >> 31) { + if (temp_cr0 >> 31) { for (i = 0; i < 8; i++) { /* Do not translate a page that has a valid lookup, as that is by definition valid and the whole purpose of the lookup is to avoid repeat identical translations. */ @@ -972,7 +986,7 @@ writememql_2386(uint32_t addr, uint64_t val) } } - if (cr0 >> 31) { + if (temp_cr0 >> 31) { addr64a[0] = mmutranslate_write_2386(addr); if (addr64a[0] > 0xffffffffULL) return; @@ -1013,13 +1027,14 @@ do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write) int i; uint32_t last_addr = addr + (num - 1); uint64_t a = 0x0000000000000000ULL; + uint32_t temp_cr0 = cpu_old_paging ? (cr0 ^ 0x80000000) : cr0; mem_debug_check_addr(addr, write ? 2 : read_type); for (i = 0; i < num; i++) a64[i] = (uint64_t) addr; - if (!(cr0 >> 31)) + if (!(temp_cr0 >> 31)) return; for (i = 0; i < num; i++) { diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index e407d43643..0d42cbd8d6 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -9,13 +9,32 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # set(net_sources) -list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c - net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c net_null.c - net_eeprom_nmc93cxx.c net_tulip.c net_rtl8139.c net_l80225.c net_modem.c utils/getline.c) +list(APPEND net_sources + network.c + net_pcap.c + net_slirp.c + net_dp8390.c + net_3c501.c + net_3c503.c + net_ne2000.c + net_pcnet.c + net_wd8003.c + net_plip.c + net_event.c + net_null.c + net_eeprom_nmc93cxx.c + net_tulip.c + net_rtl8139.c + net_l80225.c + net_modem.c + utils/getline.c +) find_package(PkgConfig REQUIRED) pkg_check_modules(SLIRP REQUIRED IMPORTED_TARGET slirp) @@ -23,6 +42,9 @@ target_link_libraries(86Box PkgConfig::SLIRP) if(WIN32) target_link_libraries(PkgConfig::SLIRP INTERFACE wsock32 ws2_32 iphlpapi iconv) + if(STATIC_BUILD) + add_compile_definitions(LIBSLIRP_STATIC) + endif() endif() if (HAIKU) diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index 1c308e9135..d6062604f4 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -384,14 +384,19 @@ dp8390_rx_common(void *priv, uint8_t *buf, int io_len) pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); /* Copy into buffer, update curpage, and signal interrupt if config'd */ - startptr = &dev->mem[(dev->curr_page * 256) - dev->mem_start]; + if (((dev->curr_page * 256) - dev->mem_start) >= dev->mem_size) + /* Do this to fix Windows 2000 crashing the emulator when its + MPU-401 probe hits the NIC. */ + startptr = dev->sink_buffer; + else + startptr = &dev->mem[(dev->curr_page * 256) - dev->mem_start]; memcpy(startptr, pkthdr, sizeof(pkthdr)); if ((nextpage > dev->curr_page) || ((dev->curr_page + pages) == dev->page_stop)) { memcpy(startptr + sizeof(pkthdr), buf, io_len); } else { endbytes = (dev->page_stop - dev->curr_page) * 256; memcpy(startptr + sizeof(pkthdr), buf, endbytes - sizeof(pkthdr)); - startptr = &dev->mem[((dev->tx_page_start * 256) - dev->mem_start) & dev->mem_wrap]; + startptr = &dev->mem[((dev->page_start * 256) - dev->mem_start) & dev->mem_wrap]; memcpy(startptr, buf + endbytes - sizeof(pkthdr), io_len - endbytes + 8); } dev->curr_page = nextpage; diff --git a/src/network/net_modem.c b/src/network/net_modem.c index 078320fb44..bb312ec315 100644 --- a/src/network/net_modem.c +++ b/src/network/net_modem.c @@ -14,7 +14,8 @@ * The DOSBox Team * * Copyright 2024 Cacodemon345 - * Copyright 2002-2021 The DOSBox Team + * Copyright (C) 2022 The DOSBox Staging Team + * Copyright (C) 2002-2021 The DOSBox Team */ #include @@ -433,7 +434,7 @@ host_to_modem_cb(void *priv) { modem_t *modem = (modem_t *) priv; - if (modem->in_warmup) + if (modem->in_warmup || (modem->serial == NULL)) goto no_write_to_machine; if ((modem->serial->type >= SERIAL_16550) && modem->serial->fifo_enabled) { @@ -575,14 +576,6 @@ modem_send_res(modem_t *modem, const ResTypes response) } else if (response_str != NULL) { modem_send_line(modem, response_str); } - - // if(CSerial::CanReceiveByte()) // very fast response - // if(rqueue->inuse() && CSerial::getRTS()) - // { uint8_t rbyte =rqueue->getb(); - // CSerial::receiveByte(rbyte); - // LOG_MSG("SERIAL: Port %" PRIu8 " modem sending byte %2x back to UART2", - // GetPortNumber(), rbyte); - // } } } @@ -624,14 +617,16 @@ modem_enter_idle_state(modem_t *modem) if (modem->listen_port) { modem->serversocket = plat_netsocket_create_server(NET_SOCKET_TCP, modem->listen_port); if (modem->serversocket == (SOCKET) -1) { - pclog("Failed to set up server on port %d\n", modem->listen_port); + modem_log("Failed to set up server on port %d\n", modem->listen_port); } } - serial_set_cts(modem->serial, 1); - serial_set_dsr(modem->serial, 1); - serial_set_dcd(modem->serial, (!modem->dcdmode ? 1 : 0)); - serial_set_ri(modem->serial, 0); + if (modem->serial != NULL) { + serial_set_cts(modem->serial, 1); + serial_set_dsr(modem->serial, 1); + serial_set_dcd(modem->serial, (!modem->dcdmode ? 1 : 0)); + serial_set_ri(modem->serial, 0); + } } void @@ -647,8 +642,11 @@ modem_enter_connected_state(modem_t *modem) plat_netsocket_close(modem->serversocket); modem->serversocket = -1; memset(&modem->telClient, 0, sizeof(modem->telClient)); - serial_set_dcd(modem->serial, 1); - serial_set_ri(modem->serial, 0); + + if (modem->serial != NULL) { + serial_set_dcd(modem->serial, 1); + serial_set_ri(modem->serial, 0); + } } void @@ -686,7 +684,7 @@ modem_dial(modem_t *modem, const char *str) { modem->tcpIpConnCounter = 0; modem->tcpIpMode = false; - if (!strncmp(str, "0.0.0.0", sizeof("0.0.0.0") - 1)) { + if (!strcmp(str, "0.0.0.0") || !strcmp(str, "0000")) { modem_log("Turning on SLIP\n"); modem_enter_connected_state(modem); modem->numberinprogress[0] = 0; @@ -710,14 +708,14 @@ modem_dial(modem_t *modem, const char *str) modem->numberinprogress[0] = 0; modem->clientsocket = plat_netsocket_create(NET_SOCKET_TCP); if (modem->clientsocket == -1) { - pclog("Failed to create client socket\n"); + modem_log("Failed to create client socket\n"); modem_send_res(modem, ResNOCARRIER); modem_enter_idle_state(modem); return; } if (-1 == plat_netsocket_connect(modem->clientsocket, buf, port)) { - pclog("Failed to connect to %s\n", buf); + modem_log("Failed to connect to %s\n", buf); modem_send_res(modem, ResNOCARRIER); modem_enter_idle_state(modem); return; @@ -1099,6 +1097,10 @@ modem_do_command(modem_t *modem, int repeat) } break; } + case '%': // % escaped commands + // Windows 98 modem prober sends unknown command AT%V + modem_send_res(modem, ResERROR); + return; case '\0': modem_send_res(modem, ResOK); return; @@ -1150,7 +1152,7 @@ fifo8_resize_2x(Fifo8 *fifo) if (!used) return; - uint8_t *temp_buf = calloc(fifo->capacity * 2, 1); + uint8_t *temp_buf = calloc(size, 1); if (!temp_buf) { fatal("net_modem: Out Of Memory!\n"); } @@ -1394,7 +1396,8 @@ modem_cmdpause_timer_callback(void *priv) } else { modem->ringing = true; modem_send_res(modem, ResRING); - serial_set_ri(modem->serial, !serial_get_ri(modem->serial)); + if (modem->serial != NULL) + serial_set_ri(modem->serial, !serial_get_ri(modem->serial)); modem->ringtimer = 3000; modem->reg[MREG_RING_COUNT] = 0; } @@ -1408,7 +1411,8 @@ modem_cmdpause_timer_callback(void *priv) return; } modem_send_res(modem, ResRING); - serial_set_ri(modem->serial, !serial_get_ri(modem->serial)); + if (modem->serial != NULL) + serial_set_ri(modem->serial, !serial_get_ri(modem->serial)); modem->ringtimer = 3000; } @@ -1443,7 +1447,8 @@ modem_cmdpause_timer_callback(void *priv) if (modem->connected) { uint8_t buffer[16]; int wouldblock = 0; - int res = plat_netsocket_receive(modem->clientsocket, buffer, sizeof(buffer), &wouldblock); + int recv = MIN(modem->rx_data.capacity - modem->rx_data.num, sizeof(buffer)); + int res = plat_netsocket_receive(modem->clientsocket, buffer, recv, &wouldblock); if (res > 0) { if (modem->telnet_mode) @@ -1491,8 +1496,8 @@ modem_init(const device_t *info) modem->clientsocket = modem->serversocket = modem->waitingclientsocket = -1; - fifo8_create(&modem->data_pending, 0x10000); - fifo8_create(&modem->rx_data, 0x10000); + fifo8_create(&modem->data_pending, 0x40000); + fifo8_create(&modem->rx_data, 0x40000); timer_add(&modem->dtr_timer, modem_dtr_callback_timer, modem, 0); timer_add(&modem->host_to_serial_timer, host_to_modem_cb, modem, 0); diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index ee32119ba4..0f3480492c 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -934,7 +934,8 @@ nic_init(const device_t *info) if (dev->board != NE2K_ETHERNEXT_MC) { dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); - if ((dev->board == NE2K_NE2000) || (dev->board == NE2K_NE2000_COMPAT)) { + if ((dev->board == NE2K_NE2000) || (dev->board == NE2K_NE2000_COMPAT) || + (dev->board == NE2K_NE2000_COMPAT_8BIT) ) { dev->bios_addr = device_get_config_hex20("bios_addr"); dev->has_bios = !!dev->bios_addr; } else { @@ -1008,6 +1009,16 @@ nic_init(const device_t *info) dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); break; + case NE2K_NE2000_COMPAT_8BIT: + dev->maclocal[0] = 0x00; /* 00:86:B0 (86Box OID) */ + dev->maclocal[1] = 0x86; + dev->maclocal[2] = 0xB0; + dev->is_8bit = 1; + rom = ROM_PATH_NE2000; + dp8390_set_defaults(dev->dp8390, DP8390_FLAG_EVEN_MAC | DP8390_FLAG_CHECK_CR | DP8390_FLAG_CLEAR_IRQ); + dp8390_mem_alloc(dev->dp8390, 0x4000, 0x4000); + break; + case NE2K_ETHERNEXT_MC: dev->maclocal[0] = 0x00; /* 00:00:D8 (Networth Inc. OID) */ dev->maclocal[1] = 0x00; @@ -1448,6 +1459,87 @@ static const device_config_t ne2000_compat_config[] = { { .name = "", .description = "", .type = CONFIG_END } }; +static const device_config_t ne2000_compat_8bit_config[] = { + { + .name = "base", + .description = "Address", + .type = CONFIG_HEX16, + .default_string = "", + .default_int = 0x320, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: board docs, https://github.com/skiselev/isa8_eth */ + { .description = "0x200", .value = 0x200 }, + { .description = "0x220", .value = 0x220 }, + { .description = "0x240", .value = 0x240 }, + { .description = "0x260", .value = 0x260 }, + { .description = "0x280", .value = 0x280 }, + { .description = "0x2a0", .value = 0x2a0 }, + { .description = "0x2c0", .value = 0x2c0 }, + { .description = "0x2e0", .value = 0x2e0 }, + { .description = "0x300", .value = 0x300 }, + { .description = "0x320", .value = 0x320 }, + { .description = "0x340", .value = 0x340 }, + { .description = "0x360", .value = 0x360 }, + { .description = "0x380", .value = 0x380 }, + { .description = "0x3a0", .value = 0x3a0 }, + { .description = "0x3c0", .value = 0x3c0 }, + { .description = "0x3e0", .value = 0x3e0 }, + { .description = "" } + }, + }, + { + .name = "irq", + .description = "IRQ", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 3, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: board docs, https://github.com/skiselev/isa8_eth */ + { .description = "IRQ 2", .value = 2 }, + { .description = "IRQ 3", .value = 3 }, + { .description = "IRQ 4", .value = 4 }, + { .description = "IRQ 5", .value = 5 }, + { .description = "IRQ 9", .value = 9 }, + { .description = "" } + }, + }, + { + .name = "mac", + .description = "MAC Address", + .type = CONFIG_MAC, + .default_string = "", + .default_int = -1 + }, + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + /* Source: board docs, https://github.com/skiselev/isa8_eth */ + { .description = "Disabled", .value = 0x00000 }, + { .description = "C000", .value = 0xC0000 }, + { .description = "C400", .value = 0xC4000 }, + { .description = "C800", .value = 0xC8000 }, + { .description = "CC00", .value = 0xCC000 }, + { .description = "D000", .value = 0xD0000 }, + { .description = "D400", .value = 0xD4000 }, + { .description = "D800", .value = 0xD8000 }, + { .description = "DC00", .value = 0xDC000 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } +}; + + static const device_config_t rtl8019as_config[] = { { .name = "mac", @@ -1545,6 +1637,20 @@ const device_t ne2000_compat_device = { .config = ne2000_compat_config }; +const device_t ne2000_compat_8bit_device = { + .name = "NE2000 Compatible 8-bit", + .internal_name = "ne2k8", + .flags = DEVICE_ISA, + .local = NE2K_NE2000_COMPAT_8BIT, + .init = nic_init, + .close = nic_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ne2000_compat_8bit_config +}; + const device_t ethernext_mc_device = { .name = "NetWorth EtherNext/MC", .internal_name = "ethernextmc", diff --git a/src/network/net_rtl8139.c b/src/network/net_rtl8139.c index 2e85d67bfe..f04f9b7a39 100644 --- a/src/network/net_rtl8139.c +++ b/src/network/net_rtl8139.c @@ -22,13 +22,14 @@ * Copyright 2011-2023 Benjamin Poirier. * Copyright 2023 Cacodemon345. */ +#include #include #include #include #include #include #include - +#define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> #include <86box/pci.h> @@ -351,7 +352,8 @@ enum chip_flags { #define RTL8139_PCI_REVID_8139 0x10 #define RTL8139_PCI_REVID_8139CPLUS 0x20 -#define RTL8139_PCI_REVID RTL8139_PCI_REVID_8139CPLUS +/* Return 0x10 - the RTL8139C+ datasheet and Windows 2000 driver both confirm this. */ +#define RTL8139_PCI_REVID RTL8139_PCI_REVID_8139 #pragma pack(push, 1) typedef struct RTL8139TallyCounters { @@ -1074,10 +1076,11 @@ rtl8139_reset(void *priv) s->cplus_enabled = 0; #if 0 - s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation s->BasicModeCtrl = 0x2100; // 100Mbps, full duplex -#endif + s->BasicModeCtrl = 0x3100; // 100Mbps, full duplex, autonegotiation s->BasicModeCtrl = 0x1000; // autonegotiation +#endif + s->BasicModeCtrl = 0x1100; // full duplex, autonegotiation rtl8139_reset_phy(s); @@ -3110,7 +3113,7 @@ rtl8139_pci_read(UNUSED(int func), int addr, void *priv) case 0x05: return s->pci_conf[addr & 0xFF] & 1; case 0x08: - return 0x20; + return RTL8139_PCI_REVID; case 0x09: return 0x0; case 0x0a: diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 599ee896d5..92434973d7 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -171,7 +171,11 @@ net_slirp_notify(void *opaque) (void) opaque; } +#if SLIRP_CHECK_VERSION(4, 8, 0) +slirp_ssize_t +#else ssize_t +#endif net_slirp_send_packet(const void *qp, size_t pkt_len, void *opaque) { net_slirp_t *slirp = (net_slirp_t *) opaque; diff --git a/src/network/net_tulip.c b/src/network/net_tulip.c index 03eb21e88a..ca43b08441 100644 --- a/src/network/net_tulip.c +++ b/src/network/net_tulip.c @@ -452,7 +452,9 @@ tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) static bool tulip_filter_address(TULIPState *s, const uint8_t *addr) { +#ifdef BLOCK_BROADCAST static const char broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif bool ret = false; for (uint8_t i = 0; i < 16 && ret == false; i++) { @@ -461,9 +463,15 @@ tulip_filter_address(TULIPState *s, const uint8_t *addr) } } +/* + Do not block broadcast packets - needed for connections to the guest + to succeed when using SLiRP. + */ +#ifdef BLOCK_BROADCAST if (!memcmp(addr, broadcast, ETH_ALEN)) { return true; } +#endif if (s->csr[6] & (CSR6_PR | CSR6_RA)) { /* Promiscuous mode enabled */ @@ -488,7 +496,7 @@ tulip_receive(void *priv, uint8_t *buf, int size) { struct tulip_descriptor desc; TULIPState *s = (TULIPState *) priv; - + int first = 1; if (size < 14 || size > sizeof(s->rx_frame) - 4 || s->rx_frame_len || tulip_rx_stopped(s)) @@ -506,7 +514,11 @@ tulip_receive(void *priv, uint8_t *buf, int size) if (!(desc.status & RDES0_OWN)) { s->csr[5] |= CSR5_RU; tulip_update_int(s); - return s->rx_frame_size - s->rx_frame_len; + if (first) + /* Stop at the very beginning, tell the host 0 bytes have been received. */ + return 0; + else + return (s->rx_frame_size - s->rx_frame_len) % s->rx_frame_size; } desc.status = 0; @@ -527,6 +539,7 @@ tulip_receive(void *priv, uint8_t *buf, int size) } tulip_desc_write(s, s->current_rx_desc, &desc); tulip_next_rx_descriptor(s, &desc); + first = 0; } while (s->rx_frame_len); return 1; @@ -1625,7 +1638,7 @@ nic_init(const device_t *info) s->pci_conf[0x04] = 7; /* Enable our BIOS space in PCI, if needed. */ - if (s->bios_addr > 0) { + if (s->has_bios) { rom_init(&s->bios_rom, ROM_PATH_DEC21140, s->bios_addr, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); tulip_pci_bar[2].addr = 0xffff0000; } else diff --git a/src/network/network.c b/src/network/network.c index d0ebe8ef38..7c02609ae5 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -54,9 +54,7 @@ #include #include #include -#ifndef _WIN32 -# include -#endif /* _WIN32 */ +#include #include #define HAVE_STDARG_H #include <86box/86box.h> @@ -77,37 +75,9 @@ # include #endif -static const device_t net_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = NET_TYPE_NONE, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -static const device_t net_internal_device = { - .name = "Internal", - .internal_name = "internal", - .flags = 0, - .local = NET_TYPE_NONE, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const device_t *net_cards[] = { - &net_none_device, - &net_internal_device, + &device_none, + &device_internal, &threec501_device, &threec503_device, &pcnet_am79c960_device, @@ -115,6 +85,7 @@ static const device_t *net_cards[] = { &de220p_device, &ne1000_compat_device, &ne2000_compat_device, + &ne2000_compat_8bit_device, &ne1000_device, &ne2000_device, &pcnet_am79c960_eb_device, @@ -149,8 +120,7 @@ int network_ndev; netdev_t network_devs[NET_HOST_INTF_MAX]; /* Local variables. */ - -#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) +#ifdef ENABLE_NETWORK_LOG int network_do_log = ENABLE_NETWORK_LOG; static FILE *network_dump = NULL; static mutex_t *network_dump_mutex; @@ -176,9 +146,15 @@ network_dump_packet(netpkt_t *pkt) struct timeval tv; gettimeofday(&tv, NULL); struct { - uint32_t ts_sec, ts_usec, incl_len, orig_len; + uint32_t ts_sec; + uint32_t ts_usec; + uint32_t incl_len; + uint32_t orig_len; } pcap_packet_hdr = { - tv.tv_sec, tv.tv_usec, pkt->len, pkt->len + .ts_sec = tv.tv_sec, + .ts_usec = tv.tv_usec, + .incl_len = pkt->len, + .orig_len = pkt->len }; if (network_dump_mutex) @@ -192,8 +168,9 @@ network_dump_packet(netpkt_t *pkt) if ((written = fwrite(pkt->data, 1, pkt->len, network_dump)) < pkt->len) { network_log("NETWORK: failed to write dump packet data\n"); fseek(network_dump, -written - sizeof(pcap_packet_hdr), SEEK_CUR); + } else { + fflush(network_dump); } - fflush(network_dump); } if (network_dump_mutex) @@ -246,28 +223,41 @@ network_init(void) #ifdef HAS_VDE // Try to load the VDE plug library - if(net_vde_prepare()==0) { + if (!net_vde_prepare()) network_devmap.has_vde = 1; - } #endif -#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) +#ifdef ENABLE_NETWORK_LOG /* Start packet dump. */ network_dump = fopen("network.pcap", "wb"); - - struct { - uint32_t magic_number; - uint16_t version_major, version_minor; - int32_t thiszone; - uint32_t sigfigs, snaplen, network; - } pcap_hdr = { - 0xa1b2c3d4, - 2, 4, - 0, - 0, 65535, 1 - }; - fwrite(&pcap_hdr, sizeof(pcap_hdr), 1, network_dump); - fflush(network_dump); + if (network_dump) { + struct { + uint32_t magic_number; + uint16_t version_major; + uint16_t version_minor; + int32_t thiszone; + uint32_t sigfigs; + uint32_t snaplen; + uint32_t network; + } pcap_hdr = { + .magic_number = 0xa1b2c3d4, + .version_major = 2, + .version_minor = 4, + .thiszone = 0, + .sigfigs = 0, + .snaplen = 65535, + .network = 1 + }; + if (fwrite(&pcap_hdr, 1, sizeof(pcap_hdr), network_dump) < sizeof(pcap_hdr)) { + network_log("NETWORK: failed to write dump header\n"); + fclose(network_dump); + network_dump = NULL; + } else { + fflush(network_dump); + } + } else { + network_log("NETWORK: failed to open dump file\n"); + } #endif } @@ -324,10 +314,8 @@ network_queue_put_swap(netqueue_t *queue, netpkt_t *src_pkt) network_log("Discarded zero length packet.\n"); } else if (src_pkt->len > NET_MAX_FRAME) { network_log("Discarded oversized packet of len=%d.\n", src_pkt->len); - network_dump_packet(src_pkt); } else { network_log("Discarded %d bytes packet because the queue is full.\n", src_pkt->len); - network_dump_packet(src_pkt); } #endif return 0; @@ -471,8 +459,9 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin network_queue_init(&card->queues[i]); } - if (!strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "modem") && net_type >= NET_TYPE_PCAP) { - /* Force SLiRP here. Modem only operates on non-Ethernet frames. */ + if ((!strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "modem") || + !strcmp(network_card_get_internal_name(net_cards_conf[net_card_current].device_num), "plip")) && (net_type >= NET_TYPE_PCAP)) { + /* Force SLiRP here. Modem and PLIP only operate on non-Ethernet frames. */ net_type = NET_TYPE_SLIRP; } @@ -528,7 +517,7 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin free(card->queued_pkt.data); free(card); // Placeholder - insert the error message - fatal("Error initializing the network device: Null driver initialization failed"); + fatal("Error initializing the network device: Null driver initialization failed\n"); return NULL; } @@ -560,7 +549,7 @@ netcard_close(netcard_t *card) void network_close(void) { -#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) +#ifdef ENABLE_NETWORK_LOG thread_close_mutex(network_dump_mutex); network_dump_mutex = NULL; #endif @@ -581,7 +570,7 @@ network_reset(void) { ui_sb_update_icon(SB_NETWORK, 0); -#if defined ENABLE_NETWORK_LOG && !defined(_WIN32) +#ifdef ENABLE_NETWORK_LOG network_dump_mutex = thread_create_mutex(); #endif @@ -625,6 +614,7 @@ network_tx_popv(netcard_t *card, netpkt_t *pkt_vec, int vec_size) for (int i = 0; i < vec_size; i++) { if (!network_queue_get_swap(queue, pkt_vec)) break; + network_dump_packet(pkt_vec); pkt_count++; pkt_vec++; } diff --git a/src/pci.c b/src/pci.c index 7865731798..b4f5eafe5a 100644 --- a/src/pci.c +++ b/src/pci.c @@ -23,6 +23,7 @@ #include <86box/86box.h> #include <86box/machine.h> #include "cpu.h" +#include "x86.h" #include <86box/io.h> #include <86box/pic.h> #include <86box/mem.h> @@ -92,7 +93,7 @@ static int pci_card; static int pci_bus; static int pci_key; static int pci_trc_reg = 0; -static uint32 pci_enable = 0x00000000; +static uint32_t pci_enable = 0x00000000; static void pci_reset_regs(void); @@ -420,7 +421,14 @@ pci_trc_reset(uint8_t val) flushmmucache(); } +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + cpu_init = 1; + else + resetx86(); +#else resetx86(); +#endif } void diff --git a/src/pit.c b/src/pit.c index 0816094cbe..8b9f23a79e 100644 --- a/src/pit.c +++ b/src/pit.c @@ -526,7 +526,7 @@ pit_timer_over(void *priv) dev->clock ^= 1; - for (uint8_t i = 0; i < 3; i++) + for (uint8_t i = 0; i < NUM_COUNTERS; i++) pit_ctr_set_clock_common(&dev->counters[i], dev->clock, dev); timer_advance_u64(&dev->callback_timer, dev->pit_const >> 1ULL); @@ -874,7 +874,7 @@ pit_device_reset(pit_t *dev) { dev->clock = 0; - for (uint8_t i = 0; i < 3; i++) + for (uint8_t i = 0; i < NUM_COUNTERS; i++) ctr_reset(&dev->counters[i]); } @@ -885,7 +885,7 @@ pit_reset(pit_t *dev) dev->clock = 0; - for (uint8_t i = 0; i < 3; i++) + for (uint8_t i = 0; i < NUM_COUNTERS; i++) ctr_reset(&dev->counters[i]); /* Disable speaker gate. */ diff --git a/src/pit_fast.c b/src/pit_fast.c index e986600eed..0d56a66164 100644 --- a/src/pit_fast.c +++ b/src/pit_fast.c @@ -47,22 +47,22 @@ #define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ #define PIT_SECONDARY 128 /* The PIT is secondary (ports 0048-004B). */ -#ifdef ENABLE_PIT_LOG -int pit_do_log = ENABLE_PIT_LOG; +#ifdef ENABLE_PIT_FAST_LOG +int pit_fast_do_log = ENABLE_PIT_FAST_LOG; static void -pit_log(const char *fmt, ...) +pit_fast_log(const char *fmt, ...) { va_list ap; - if (pit_do_log) { + if (pit_fast_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); } } #else -# define pit_log(fmt, ...) +# define pit_fast_log(fmt, ...) #endif static void @@ -420,7 +420,7 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) int t = (addr & 3); ctrf_t *ctr; - pit_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); + pit_fast_log("[%04X:%08X] pit_write(%04X, %02X, %08X)\n", CS, cpu_state.pc, addr, val, priv); cycles -= ISA_CYCLES(8); @@ -438,7 +438,7 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) pitf_ctr_latch_count(&dev->counters[1]); if (val & 8) pitf_ctr_latch_count(&dev->counters[2]); - pit_log("PIT %i: Initiated readback command\n", t); + pit_fast_log("PIT %i: Initiated readback command\n", t); } if (!(val & 0x10)) { if (val & 2) @@ -456,7 +456,7 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) if (!(dev->ctrl & 0x30)) { pitf_ctr_latch_count(ctr); dev->ctrl |= 0x30; - pit_log("PIT %i: Initiated latched read, %i bytes latched\n", + pit_fast_log("PIT %i: Initiated latched read, %i bytes latched\n", t, ctr->latched); } else { ctr->ctrl = val; @@ -476,7 +476,7 @@ pitf_write(uint16_t addr, uint8_t val, void *priv) pitf_ctr_set_out(ctr, 1, dev); ctr->disabled = 1; - pit_log("PIT %i: M = %i, RM/WM = %i, State = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->state, ctr->out); + pit_fast_log("PIT %i: M = %i, RM/WM = %i, Out = %i\n", t, ctr->m, ctr->rm, ctr->out); } ctr->thit = 0; } @@ -619,7 +619,7 @@ pitf_read(uint16_t addr, void *priv) break; } - pit_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); + pit_fast_log("[%04X:%08X] pit_read(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret); return ret; } @@ -670,7 +670,7 @@ pitf_reset(pitf_t *dev) { memset(dev, 0, sizeof(pitf_t)); - for (uint8_t i = 0; i < 3; i++) + for (uint8_t i = 0; i < NUM_COUNTERS; i++) ctr_reset(&dev->counters[i]); /* Disable speaker gate. */ @@ -683,7 +683,7 @@ pitf_set_pit_const(void *data, uint64_t pit_const) pitf_t *pit = (pitf_t *) data; ctrf_t *ctr; - for (uint8_t i = 0; i < 3; i++) { + for (uint8_t i = 0; i < NUM_COUNTERS; i++) { ctr = &pit->counters[i]; ctr->pit_const = pit_const; } @@ -728,7 +728,7 @@ pitf_init(const device_t *info) dev->flags = info->local; if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { - for (int i = 0; i < 3; i++) { + for (int i = 0; i < NUM_COUNTERS; i++) { ctrf_t *ctr = &dev->counters[i]; ctr->priv = dev; timer_add(&ctr->timer, pitf_timer_over, (void *) ctr, 0); diff --git a/src/port_92.c b/src/port_92.c index 1307ecba93..18e60326c4 100644 --- a/src/port_92.c +++ b/src/port_92.c @@ -36,6 +36,7 @@ #define PORT_92_PCI 4 #define PORT_92_RESET 8 #define PORT_92_A20 16 +#define PORT_92_KEY 32 static uint8_t port_92_readb(uint16_t port, void *priv) @@ -46,7 +47,10 @@ port_92_readb(uint16_t port, void *priv) if (port == 0x92) { /* Return bit 1 directly from mem_a20_alt, so the pin can be reset independently of the device. */ - ret = (dev->reg & ~0x03) | (mem_a20_alt & 2) | (cpu_alt_reset & 1); + if (dev->flags & PORT_92_KEY) + ret = (dev->reg & ~0x03) | (mem_a20_key & 2) | (cpu_alt_reset & 1); + else + ret = (dev->reg & ~0x03) | (mem_a20_alt & 2) | (cpu_alt_reset & 1); if (dev->flags & PORT_92_INV) ret |= 0xfc; @@ -94,8 +98,11 @@ port_92_writeb(uint16_t port, uint8_t val, void *priv) dev->reg = val & 0x03; - if ((mem_a20_alt ^ val) & 2) { - mem_a20_alt = (val & 2); + if (dev->flags & PORT_92_KEY) { + mem_a20_key = val & 2; + mem_a20_recalc(); + } else if ((mem_a20_alt ^ val) & 2) { + mem_a20_alt = (mem_a20_alt & 0xfd) | (val & 2); mem_a20_recalc(); } @@ -234,6 +241,20 @@ const device_t port_92_device = { .config = NULL }; +const device_t port_92_key_device = { + .name = "Port 92 Register (using A20 key)", + .internal_name = "port_92_key", + .flags = 0, + .local = PORT_92_KEY, + .init = port_92_init, + .close = port_92_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t port_92_inv_device = { .name = "Port 92 Register (inverted bits 2-7)", .internal_name = "port_92_inv", diff --git a/src/printer/CMakeLists.txt b/src/printer/CMakeLists.txt index dea0c7fbe8..071bf71136 100644 --- a/src/printer/CMakeLists.txt +++ b/src/printer/CMakeLists.txt @@ -9,11 +9,23 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(print OBJECT png.c prt_cpmap.c prt_escp.c prt_text.c prt_ps.c) +add_library(print OBJECT + png.c + prt_cpmap.c + prt_escp.c + prt_text.c + prt_ps.c +) + +if(PCL) + target_compile_definitions(print PRIVATE USE_PCL) +endif() if(APPLE) find_library(GHOSTSCRIPT_LIB gs) @@ -26,9 +38,9 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(FREETYPE REQUIRED IMPORTED_TARGET freetype2) target_link_libraries(86Box PkgConfig::FREETYPE) if(STATIC_BUILD) - if(QT) + # if(QT) # Qt provides its own version of harfbuzz which leads to duplicated symbols. target_link_options(86Box PRIVATE "LINKER:--allow-multiple-definition") - endif() + # endif() target_link_libraries(86Box -static ${FREETYPE_STATIC_LIBRARIES}) endif() diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index e6362019f4..dcd018881f 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -6,13 +6,16 @@ * * This file is part of the 86Box distribution. * - * Implementation of a generic PostScript printer. + * Implementation of a generic PostScript printer and a + * generic PCL 5e printer. * * * * Authors: David Hrdlička, + * Cacodemon345 * * Copyright 2019 David Hrdlička. + * Copyright 2024 Cacodemon345. */ #include @@ -44,15 +47,21 @@ #ifdef _WIN32 # if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) # define PATH_GHOSTSCRIPT_DLL "gsdll32.dll" +# define PATH_GHOSTPCL_DLL "gpcl6dll32.dll" # else # define PATH_GHOSTSCRIPT_DLL "gsdll64.dll" +# define PATH_GHOSTPCL_DLL "gpcl6dll64.dll" # endif #elif defined __APPLE__ # define PATH_GHOSTSCRIPT_DLL "libgs.dylib" +# define PATH_GHOSTPCL_DLL "libgpcl6.9.54.dylib" #else # define PATH_GHOSTSCRIPT_DLL "libgs.so.9" # define PATH_GHOSTSCRIPT_DLL_ALT1 "libgs.so.10" # define PATH_GHOSTSCRIPT_DLL_ALT2 "libgs.so" +# define PATH_GHOSTPCL_DLL "libgpcl6.so.9" +# define PATH_GHOSTPCL_DLL_ALT1 "libgpcl6.so.10" +# define PATH_GHOSTPCL_DLL_ALT2 "libgpcl6.so" #endif #define POSTSCRIPT_BUFFER_LENGTH 65536 @@ -72,6 +81,8 @@ typedef struct ps_t { bool int_pending; bool error; bool autofeed; + bool pcl; + bool pcl_escape; uint8_t ctrl; char printer_path[260]; @@ -141,28 +152,32 @@ pulse_timer(void *priv) static int convert_to_pdf(ps_t *dev) { - volatile int code; + volatile int code, arg = 0; void *instance = NULL; char input_fn[1024]; char output_fn[1024]; - char *gsargv[9]; + char *gsargv[11]; strcpy(input_fn, dev->printer_path); path_slash(input_fn); strcat(input_fn, dev->filename); strcpy(output_fn, input_fn); - strcpy(output_fn + strlen(output_fn) - 3, ".pdf"); - - gsargv[0] = ""; - gsargv[1] = "-dNOPAUSE"; - gsargv[2] = "-dBATCH"; - gsargv[3] = "-dSAFER"; - gsargv[4] = "-sDEVICE=pdfwrite"; - gsargv[5] = "-q"; - gsargv[6] = "-o"; - gsargv[7] = output_fn; - gsargv[8] = input_fn; + strcpy(output_fn + strlen(output_fn) - (dev->pcl ? 4 : 3), ".pdf"); + + gsargv[arg++] = ""; + gsargv[arg++] = "-dNOPAUSE"; + gsargv[arg++] = "-dBATCH"; + gsargv[arg++] = "-dSAFER"; + gsargv[arg++] = "-sDEVICE=pdfwrite"; + if (dev->pcl) { + gsargv[arg++] = "-LPCL"; + gsargv[arg++] = "-lPCL5E"; + } + gsargv[arg++] = "-q"; + gsargv[arg++] = "-o"; + gsargv[arg++] = output_fn; + gsargv[arg++] = input_fn; code = gsapi_new_instance(&instance, dev); if (code < 0) @@ -171,7 +186,7 @@ convert_to_pdf(ps_t *dev) code = gsapi_set_arg_encoding(instance, GS_ARG_ENCODING_UTF8); if (code == 0) - code = gsapi_init_with_args(instance, 9, gsargv); + code = gsapi_init_with_args(instance, arg, gsargv); if (code == 0 || code == gs_error_Quit) code = gsapi_exit(instance); @@ -198,19 +213,22 @@ write_buffer(ps_t *dev, bool finish) return; if (dev->filename[0] == 0) - plat_tempfile(dev->filename, NULL, ".ps"); + plat_tempfile(dev->filename, NULL, dev->pcl ? ".pcl" : ".ps"); strcpy(path, dev->printer_path); path_slash(path); strcat(path, dev->filename); - fp = plat_fopen(path, "a"); + fp = plat_fopen(path, dev->pcl ? "ab" : "a"); if (fp == NULL) return; fseek(fp, 0, SEEK_END); - fprintf(fp, "%.*s", POSTSCRIPT_BUFFER_LENGTH, dev->buffer); + if (dev->pcl) + fwrite(dev->buffer, 1, dev->buffer_pos, fp); + else + fprintf(fp, "%.*s", POSTSCRIPT_BUFFER_LENGTH, dev->buffer); fclose(fp); @@ -249,8 +267,25 @@ ps_write_data(uint8_t val, void *priv) static void process_data(ps_t *dev) { - /* Check for non-printable characters */ - if ((dev->data < 0x20) || (dev->data == 0x7f)) { + /* On PCL, check for escape sequences. */ + if (dev->pcl) { + if (dev->data == 0x1B) + dev->pcl_escape = true; + else if (dev->pcl_escape) { + dev->pcl_escape = false; + if (dev->data == 0xE) { + dev->buffer[dev->buffer_pos++] = dev->data; + dev->buffer[dev->buffer_pos] = 0; + + if (dev->buffer_pos > 2) + write_buffer(dev, true); + + return; + } + } + } + /* On PostScript, check for non-printable characters. */ + else if ((dev->data < 0x20) || (dev->data == 0x7f)) { switch (dev->data) { /* The following characters are considered white-space by the PostScript specification */ @@ -376,6 +411,57 @@ ps_init(void *lpt) return dev; } +#ifdef USE_PCL +static void * +pcl_init(void *lpt) +{ + ps_t *dev; + gsapi_revision_t rev; + + dev = (ps_t *) malloc(sizeof(ps_t)); + memset(dev, 0x00, sizeof(ps_t)); + dev->ctrl = 0x04; + dev->lpt = lpt; + dev->pcl = true; + + /* Try loading the DLL. */ + ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL, ghostscript_imports); +#ifdef PATH_GHOSTPCL_DLL_ALT1 + if (ghostscript_handle == NULL) { + ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT1, ghostscript_imports); +# ifdef PATH_GHOSTPCL_DLL_ALT2 + if (ghostscript_handle == NULL) + ghostscript_handle = dynld_module(PATH_GHOSTPCL_DLL_ALT2, ghostscript_imports); +# endif + } +#endif + if (ghostscript_handle == NULL) { + ui_msgbox_header(MBX_ERROR, plat_get_string(STRING_GHOSTPCL_ERROR_TITLE), plat_get_string(STRING_GHOSTPCL_ERROR_DESC)); + } else { + if (gsapi_revision(&rev, sizeof(rev)) == 0) { + pclog("Loaded %s, rev %ld (%ld)\n", rev.product, rev.revision, rev.revisiondate); + } else { + dynld_close(ghostscript_handle); + ghostscript_handle = NULL; + } + } + + /* Cache print folder path. */ + memset(dev->printer_path, 0x00, sizeof(dev->printer_path)); + path_append_filename(dev->printer_path, usr_path, "printer"); + if (!plat_dir_check(dev->printer_path)) + plat_dir_create(dev->printer_path); + path_slash(dev->printer_path); + + timer_add(&dev->pulse_timer, pulse_timer, dev, 0); + timer_add(&dev->timeout_timer, timeout_timer, dev, 0); + + reset_ps(dev); + + return dev; +} +#endif + static void ps_close(void *priv) { @@ -406,3 +492,17 @@ const lpt_device_t lpt_prt_ps_device = { .read_status = ps_read_status, .read_ctrl = NULL }; + +#ifdef USE_PCL +const lpt_device_t lpt_prt_pcl_device = { + .name = "Generic PCL5e Printer", + .internal_name = "pcl", + .init = pcl_init, + .close = ps_close, + .write_data = ps_write_data, + .write_ctrl = ps_write_ctrl, + .read_data = NULL, + .read_status = ps_read_status, + .read_ctrl = NULL +}; +#endif diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 1e9c76378c..c21dfd5bb3 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -8,6 +8,11 @@ # # CMake build script. # +# Authors: David Hrdlička, +# Jasmine Iwanek, +# +# Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) @@ -41,8 +46,12 @@ endif() set(CMAKE_FIND_PACKAGE_PREFER_CONFIG OFF) find_package(Threads REQUIRED) -find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets Network OpenGL REQUIRED) +find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets Network OpenGL Gui REQUIRED) find_package(Qt${QT_MAJOR}LinguistTools REQUIRED NO_CMAKE_FIND_ROOT_PATH) +if(NOT USE_QT6) + # For in src/qt/qt_mainwindow.cpp + include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) +endif () # TODO: Is this the correct way to do this, and is it required on any # other platforms or with Qt 5? @@ -186,6 +195,10 @@ if(RTMIDI) target_compile_definitions(ui PRIVATE USE_RTMIDI) endif() +if(WACOM) + target_compile_definitions(ui PRIVATE USE_WACOM) +endif() + if(WIN32) enable_language(RC) target_sources(86Box PUBLIC 86Box-qt.rc) @@ -219,10 +232,20 @@ if(WIN32 AND NOT MINGW) target_sources(plat PRIVATE win_opendir.c) endif() +if(WIN32 AND NOT CPPTHREADS) + target_sources(plat PRIVATE win_thread.c) +endif() + if(WIN32) - target_sources(plat PRIVATE win_serial_passthrough.c win_netsocket.c) + target_sources(plat PRIVATE + win_serial_passthrough.c + win_netsocket.c + ) else() - target_sources(plat PRIVATE ../unix/unix_serial_passthrough.c ../unix/unix_netsocket.c) + target_sources(plat PRIVATE + ../unix/unix_serial_passthrough.c + ../unix/unix_netsocket.c + ) endif() if(WIN32) @@ -256,18 +279,14 @@ if (WIN32) ) endif() -target_link_libraries( - plat - PRIVATE +target_link_libraries(plat PRIVATE Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::Gui Qt${QT_MAJOR}::Network Threads::Threads ) -target_link_libraries( - ui - PRIVATE +target_link_libraries(ui PRIVATE Qt${QT_MAJOR}::Widgets Qt${QT_MAJOR}::Gui Qt${QT_MAJOR}::OpenGL @@ -400,7 +419,7 @@ if (UNIX AND NOT APPLE AND NOT HAIKU) target_compile_definitions(ui PRIVATE XKBCOMMON_X11) target_link_libraries(ui PRIVATE X11::xcb PUBLIC PkgConfig::XKBCOMMON_X11) target_sources(ui PRIVATE xkbcommon_x11_keyboard.cpp) - set(QT5_PRIVATE_HEADERS ON) + set(QT_PRIVATE_HEADERS ON) endif() endif() endif() @@ -422,13 +441,13 @@ if (UNIX AND NOT APPLE AND NOT HAIKU) target_sources(ui PRIVATE xkbcommon_wl_keyboard.cpp) endif() target_compile_definitions(ui PRIVATE WAYLAND) - set(QT5_PRIVATE_HEADERS ON) + set(QT_PRIVATE_HEADERS ON) endif() endif() endif() # Add private headers for Qt5 if required. - if (NOT USE_QT6 AND DEFINED QT5_PRIVATE_HEADERS) + if (DEFINED QT_PRIVATE_HEADERS) find_package(Qt${QT_MAJOR}Gui) if (Qt${QT_MAJOR}Gui_FOUND) include_directories(${Qt${QT_MAJOR}Gui_PRIVATE_INCLUDE_DIRS}) diff --git a/src/qt/dummy_cdrom_ioctl.c b/src/qt/dummy_cdrom_ioctl.c index cb08246756..5c533b216f 100644 --- a/src/qt/dummy_cdrom_ioctl.c +++ b/src/qt/dummy_cdrom_ioctl.c @@ -167,8 +167,6 @@ plat_cdrom_get_audio_track_info(UNUSED(int end), int track, int *track_num, TMSF int plat_cdrom_get_audio_sub(UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) { - long size = 0; - *track = 1; *attr = 0x14; *index = 1; @@ -197,10 +195,6 @@ plat_cdrom_get_sector_size(UNUSED(uint32_t sector)) int plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) { - int status; - long size = 0; - int buflen = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - plat_cdrom_open(); if (raw) { diff --git a/src/qt/icons/cdrom_folder.ico b/src/qt/icons/cdrom_folder.ico new file mode 100644 index 0000000000..be8386b87e Binary files /dev/null and b/src/qt/icons/cdrom_folder.ico differ diff --git a/src/qt/icons/cdrom_host.ico b/src/qt/icons/cdrom_host.ico new file mode 100644 index 0000000000..5065f347a5 Binary files /dev/null and b/src/qt/icons/cdrom_host.ico differ diff --git a/src/qt/icons/cdrom_image.ico b/src/qt/icons/cdrom_image.ico new file mode 100644 index 0000000000..84fc233e20 Binary files /dev/null and b/src/qt/icons/cdrom_image.ico differ diff --git a/src/qt/icons/cdrom_mute.ico b/src/qt/icons/cdrom_mute.ico new file mode 100644 index 0000000000..237c8b0650 Binary files /dev/null and b/src/qt/icons/cdrom_mute.ico differ diff --git a/src/qt/icons/cdrom_unmute.ico b/src/qt/icons/cdrom_unmute.ico new file mode 100644 index 0000000000..8e4cc70ed7 Binary files /dev/null and b/src/qt/icons/cdrom_unmute.ico differ diff --git a/src/qt/icons/warning.ico b/src/qt/icons/warning.ico new file mode 100644 index 0000000000..2f283e2c42 Binary files /dev/null and b/src/qt/icons/warning.ico differ diff --git a/src/qt/languages/fr-FR.po b/src/qt/languages/fr-FR.po index f7687132f1..db16abe070 100644 --- a/src/qt/languages/fr-FR.po +++ b/src/qt/languages/fr-FR.po @@ -741,6 +741,9 @@ msgstr "T" msgid "S" msgstr "S" +msgid "MiB" +msgstr "Mio" + msgid "KB" msgstr "Ko" diff --git a/src/qt/languages/ru-RU.po b/src/qt/languages/ru-RU.po index a4103c3e8d..eb3c891743 100644 --- a/src/qt/languages/ru-RU.po +++ b/src/qt/languages/ru-RU.po @@ -831,6 +831,9 @@ msgstr "H" msgid "S" msgstr "S" +msgid "MiB" +msgstr "МиБ" + msgid "KB" msgstr "КБ" diff --git a/src/qt/languages/uk-UA.po b/src/qt/languages/uk-UA.po index 8dca70a854..9c76d803ee 100644 --- a/src/qt/languages/uk-UA.po +++ b/src/qt/languages/uk-UA.po @@ -741,6 +741,9 @@ msgstr "H" msgid "S" msgstr "S" +msgid "MiB" +msgstr "МіБ" + msgid "KB" msgstr "КБ" diff --git a/src/qt/qt.c b/src/qt/qt.c index 47f5b94100..a9a6460eb0 100644 --- a/src/qt/qt.c +++ b/src/qt/qt.c @@ -38,7 +38,7 @@ qt_nvr_save(void) char icon_set[256] = ""; /* name of the iconset to be used */ int -plat_vidapi(char *api) +plat_vidapi(const char *api) { if (!strcasecmp(api, "default") || !strcasecmp(api, "system")) { return 0; diff --git a/src/qt/qt_deviceconfig.cpp b/src/qt/qt_deviceconfig.cpp index b031e65445..21f9a7e808 100644 --- a/src/qt/qt_deviceconfig.cpp +++ b/src/qt/qt_deviceconfig.cpp @@ -120,6 +120,9 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep) int p; int q; + if (config == NULL) + return; + while (config->type != -1) { const int config_type = config->type & CONFIG_TYPE_MASK; @@ -295,7 +298,7 @@ DeviceConfig::ProcessConfig(void *dc, const void *c, const bool is_dep) int currentIndex = 0; auto serialDevices = EnumerateSerialDevices(); - Models::AddEntry(model, "None", -1); + Models::AddEntry(model, tr("None"), -1); for (int i = 0; i < serialDevices.size(); i++) { const int row = Models::AddEntry(model, serialDevices[i], i); if (selected == serialDevices[i]) @@ -363,7 +366,11 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se dc.ProcessConfig(&device_context, config, false); dc.setFixedSize(dc.minimumSizeHint()); + if (dc.exec() == QDialog::Accepted) { + if (config == NULL) + return; + config = device->config; while (config->type != -1) { switch (config->type) { @@ -394,7 +401,7 @@ DeviceConfig::ConfigureDevice(const _device_ *device, int instance, Settings *se { auto *cbox = dc.findChild(config->name); auto path = cbox->currentText().toUtf8(); - if (path == "None") + if (cbox->currentData().toInt() == -1) path = ""; config_set_string(device_context.name, const_cast(config->name), path); break; diff --git a/src/qt/qt_harddiskdialog.cpp b/src/qt/qt_harddiskdialog.cpp index df10a6d382..f2326ef8bb 100644 --- a/src/qt/qt_harddiskdialog.cpp +++ b/src/qt/qt_harddiskdialog.cpp @@ -20,6 +20,9 @@ #include "ui_qt_harddiskdialog.h" extern "C" { +#ifdef __unix__ +#include +#endif #include <86box/86box.h> #include <86box/hdd.h> #include "../disk/minivhd/minivhd.h" @@ -447,6 +450,7 @@ HarddiskDialog::onCreateNewFile() } // formats 0, 1 and 2 +#ifndef __unix__ connect(this, &HarddiskDialog::fileProgress, this, [this](int value) { ui->progressBar->setValue(value); QApplication::processEvents(); }); ui->progressBar->setVisible(true); [size, &file, this] { @@ -469,6 +473,13 @@ HarddiskDialog::onCreateNewFile() } emit fileProgress(100); }(); +#else + int ret = ftruncate(file.handle(), (size_t) size); + + if (ret) { + QMessageBox::critical(this, tr("Unable to write file"), tr("Make sure the file is being saved to a writable directory.")); + } +#endif QMessageBox::information(this, tr("Disk image created"), tr("Remember to partition and format the newly-created drive.")); setResult(QDialog::Accepted); diff --git a/src/qt/qt_joystickconfiguration.cpp b/src/qt/qt_joystickconfiguration.cpp index e03d57e09b..8489dfd22a 100644 --- a/src/qt/qt_joystickconfiguration.cpp +++ b/src/qt/qt_joystickconfiguration.cpp @@ -36,7 +36,7 @@ JoystickConfiguration::JoystickConfiguration(int type, int joystick_nr, QWidget ui->setupUi(this); auto model = ui->comboBoxDevice->model(); - Models::AddEntry(model, "None", 0); + Models::AddEntry(model, tr("None"), 0); for (int c = 0; c < joysticks_present; c++) { Models::AddEntry(model, plat_joystick_state[c].name, c + 1); } @@ -114,8 +114,8 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) } for (int d = 0; d < plat_joystick_state[joystick].nr_povs; d++) { - Models::AddEntry(model, QString("%1 (X axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); - Models::AddEntry(model, QString("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); + Models::AddEntry(model, tr("%1 (X axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); + Models::AddEntry(model, tr("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); } int nr_axes = plat_joystick_state[joystick].nr_axes; @@ -161,9 +161,9 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) for (int c = 0; c < joystick_get_pov_count(type) * 2; c++) { QLabel *label; if (c & 1) { - label = new QLabel(QString("%1 (Y axis)").arg(joystick_get_pov_name(type, c / 2)), this); + label = new QLabel(tr("%1 (Y axis)").arg(joystick_get_pov_name(type, c / 2)), this); } else { - label = new QLabel(QString("%1 (X axis)").arg(joystick_get_pov_name(type, c / 2)), this); + label = new QLabel(tr("%1 (X axis)").arg(joystick_get_pov_name(type, c / 2)), this); } auto cbox = new QComboBox(this); cbox->setObjectName(QString("cboxPov%1").arg(QString::number(c))); @@ -171,8 +171,8 @@ JoystickConfiguration::on_comboBoxDevice_currentIndexChanged(int index) auto model = cbox->model(); for (int d = 0; d < plat_joystick_state[joystick].nr_povs; d++) { - Models::AddEntry(model, QString("%1 (X axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); - Models::AddEntry(model, QString("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); + Models::AddEntry(model, tr("%1 (X axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); + Models::AddEntry(model, tr("%1 (Y axis)").arg(plat_joystick_state[joystick].pov[d].name), 0); } for (int d = 0; d < plat_joystick_state[joystick].nr_axes; d++) { diff --git a/src/qt/qt_machinestatus.cpp b/src/qt/qt_machinestatus.cpp index a074f556ef..ebc18e1985 100644 --- a/src/qt/qt_machinestatus.cpp +++ b/src/qt/qt_machinestatus.cpp @@ -61,6 +61,8 @@ extern uint64_t tsc; extern MainWindow *main_window; +static bool sbar_initialized = false; + namespace { struct PixmapSetActive { QPixmap normal; @@ -294,7 +296,7 @@ MachineStatus::iterateFDD(const std::function &cb) void MachineStatus::iterateCDROM(const std::function &cb) { - auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + auto hdc_name = QString(hdc_get_internal_name(hdc_current[0])); for (size_t i = 0; i < CDROM_NUM; i++) { /* Could be Internal or External IDE.. */ if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && !hasIDE() && @@ -317,7 +319,7 @@ MachineStatus::iterateCDROM(const std::function &cb) void MachineStatus::iterateZIP(const std::function &cb) { - auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + auto hdc_name = QString(hdc_get_internal_name(hdc_current[0])); for (size_t i = 0; i < ZIP_NUM; i++) { /* Could be Internal or External IDE.. */ if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && !hasIDE() && @@ -338,7 +340,7 @@ MachineStatus::iterateZIP(const std::function &cb) void MachineStatus::iterateMO(const std::function &cb) { - auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + auto hdc_name = QString(hdc_get_internal_name(hdc_current[0])); for (size_t i = 0; i < MO_NUM; i++) { /* Could be Internal or External IDE.. */ if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && !hasIDE() && @@ -380,6 +382,31 @@ hdd_count(int bus) return c; } +void +MachineStatus::refreshEmptyIcons() +{ + /* Check if icons are initialized. */ + if (!sbar_initialized) + return; + + for (size_t i = 0; i < FDD_NUM; ++i) + d->fdd[i].setEmpty(machine_status.fdd[i].empty); + for (size_t i = 0; i < CDROM_NUM; ++i) + d->cdrom[i].setEmpty(machine_status.cdrom[i].empty); + for (size_t i = 0; i < ZIP_NUM; i++) + d->zip[i].setEmpty(machine_status.zip[i].empty); + for (size_t i = 0; i < MO_NUM; i++) + d->mo[i].setEmpty(machine_status.mo[i].empty); + + d->cassette.setEmpty(machine_status.cassette.empty); + + for (size_t i = 0; i < NET_CARD_MAX; i++) + d->net[i].setEmpty(machine_status.net[i].empty); + + for (int i = 0; i < 2; ++i) + d->cartridge[i].setEmpty(machine_status.cartridge[i].empty); +} + void MachineStatus::refreshIcons() { @@ -387,37 +414,32 @@ MachineStatus::refreshIcons() if (!update_icons) return; - for (size_t i = 0; i < FDD_NUM; ++i) { + for (size_t i = 0; i < FDD_NUM; ++i) d->fdd[i].setActive(machine_status.fdd[i].active); - d->fdd[i].setEmpty(machine_status.fdd[i].empty); - } for (size_t i = 0; i < CDROM_NUM; ++i) { d->cdrom[i].setActive(machine_status.cdrom[i].active); - d->cdrom[i].setEmpty(machine_status.cdrom[i].empty); + if (machine_status.cdrom[i].active) + ui_sb_update_icon(SB_CDROM | i, 0); } for (size_t i = 0; i < ZIP_NUM; i++) { d->zip[i].setActive(machine_status.zip[i].active); - d->zip[i].setEmpty(machine_status.zip[i].empty); + if (machine_status.zip[i].active) + ui_sb_update_icon(SB_ZIP | i, 0); } for (size_t i = 0; i < MO_NUM; i++) { d->mo[i].setActive(machine_status.mo[i].active); - d->mo[i].setEmpty(machine_status.mo[i].empty); + if (machine_status.mo[i].active) + ui_sb_update_icon(SB_MO | i, 0); } - d->cassette.setEmpty(machine_status.cassette.empty); - for (size_t i = 0; i < HDD_BUS_USB; i++) { d->hdds[i].setActive(machine_status.hdd[i].active); + if (machine_status.hdd[i].active) + ui_sb_update_icon(SB_HDD | i, 0); } - for (size_t i = 0; i < NET_CARD_MAX; i++) { + for (size_t i = 0; i < NET_CARD_MAX; i++) d->net[i].setActive(machine_status.net[i].active); - d->net[i].setEmpty(machine_status.net[i].empty); - } - - for (int i = 0; i < 2; ++i) { - d->cartridge[i].setEmpty(machine_status.cartridge[i].empty); - } } void @@ -591,7 +613,7 @@ MachineStatus::refresh(QStatusBar *sbar) sbar->addWidget(d->net[i].label.get()); }); - auto hdc_name = QString(hdc_get_internal_name(hdc_current)); + auto hdc_name = QString(hdc_get_internal_name(hdc_current[0])); if ((has_mfm || (hdc_name.left(5) == QStringLiteral("st506"))) && (c_mfm > 0)) { d->hdds[HDD_BUS_MFM].label = std::make_unique(); d->hdds[HDD_BUS_MFM].setActive(false); @@ -653,6 +675,10 @@ MachineStatus::refresh(QStatusBar *sbar) sbar->addWidget(d->sound.get()); d->text = std::make_unique(); sbar->addWidget(d->text.get()); + + sbar_initialized = true; + + refreshEmptyIcons(); } void @@ -708,4 +734,6 @@ MachineStatus::updateTip(int tag) case SB_TEXT: break; } + + refreshEmptyIcons(); } diff --git a/src/qt/qt_machinestatus.hpp b/src/qt/qt_machinestatus.hpp index cf706180d7..fc0e33e911 100644 --- a/src/qt/qt_machinestatus.hpp +++ b/src/qt/qt_machinestatus.hpp @@ -75,6 +75,7 @@ public slots: void refresh(QStatusBar *sbar); void message(const QString &msg); void updateTip(int tag); + void refreshEmptyIcons(); void refreshIcons(); private: diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 87b86f8e92..a50c538206 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -138,16 +138,27 @@ main_thread_fn() } } else { /* Just so we dont overload the host OS. */ + + /* Trigger a hard reset if one is pending. */ + if (hard_reset_pending) { + hard_reset_pending = 0; + pc_reset_hard_close(); + pc_reset_hard_init(); + } + if (dopause) ack_pause(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } is_quit = 1; - if (gfxcard[1]) { - ui_deinit_monitor(1); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { + if (gfxcard[i]) { + ui_deinit_monitor(i); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } } QTimer::singleShot(0, QApplication::instance(), []() { QApplication::processEvents(); QApplication::instance()->quit(); }); } @@ -240,13 +251,13 @@ main(int argc, char *argv[]) #ifdef Q_OS_WINDOWS # if !defined(EMU_BUILD_NUM) || (EMU_BUILD_NUM != 5624) - HWND winbox = FindWindow("TWinBoxMain", NULL); + HWND winbox = FindWindowW(L"TWinBoxMain", NULL); if (winbox && - FindWindowEx(winbox, NULL, "TToolBar", NULL) && - FindWindowEx(winbox, NULL, "TListBox", NULL) && - FindWindowEx(winbox, NULL, "TStatusBar", NULL) && - (winbox = FindWindowEx(winbox, NULL, "TPageControl", NULL)) && /* holds a TTabSheet even on VM pages */ - FindWindowEx(winbox, NULL, "TTabSheet", NULL)) + FindWindowExW(winbox, NULL, L"TToolBar", NULL) && + FindWindowExW(winbox, NULL, L"TListBox", NULL) && + FindWindowExW(winbox, NULL, L"TStatusBar", NULL) && + (winbox = FindWindowExW(winbox, NULL, L"TPageControl", NULL)) && /* holds a TTabSheet even on VM pages */ + FindWindowExW(winbox, NULL, L"TTabSheet", NULL)) # endif { QMessageBox warningbox(QMessageBox::Icon::Warning, QObject::tr("WinBox is no longer supported"), diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index c48dfd052b..b06473a8a6 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -205,7 +205,8 @@ MainWindow::MainWindow(QWidget *parent) connect(this, &MainWindow::hardResetCompleted, this, [this]() { ui->actionMCA_devices->setVisible(machine_has_bus(machine, MACHINE_BUS_MCA)); - QApplication::setOverrideCursor(Qt::ArrowCursor); + while (QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); #ifdef USE_WACOM ui->menuTablet_tool->menuAction()->setVisible(mouse_input_mode >= 1); #else @@ -213,7 +214,7 @@ MainWindow::MainWindow(QWidget *parent) #endif }); - connect(this, &MainWindow::showMessageForNonQtThread, this, &MainWindow::showMessage_, Qt::BlockingQueuedConnection); + connect(this, &MainWindow::showMessageForNonQtThread, this, &MainWindow::showMessage_, Qt::QueuedConnection); connect(this, &MainWindow::setTitle, this, [this, toolbar_label](const QString &title) { if (dopause && !hide_tool_bar) { @@ -945,10 +946,9 @@ MainWindow::on_actionSettings_triggered() default: break; case QDialog::Accepted: - pc_reset_hard_close(); settings.save(); config_changed = 2; - pc_reset_hard_init(); + pc_reset_hard(); break; case QDialog::Rejected: break; @@ -997,7 +997,7 @@ MainWindow::processKeyboardInput(bool down, uint32_t keycode) case 0x10b: /* Microsoft scroll up normal */ case 0x180 ... 0x1ff: /* E0 break codes (including Microsoft scroll down normal) */ /* This key uses a break code as make. Send it manually, only on press. */ - if (down) { + if (down && (mouse_capture || !kbd_req_capture || video_fullscreen)) { if (keycode & 0x100) keyboard_send(0xe0); keyboard_send(keycode & 0xff); @@ -1010,7 +1010,7 @@ MainWindow::processKeyboardInput(bool down, uint32_t keycode) break; case 0x137: /* Print Screen */ - if (keyboard_recv(0x38) || keyboard_recv(0x138)) { /* Alt+ */ + if (keyboard_recv_ui(0x38) || keyboard_recv_ui(0x138)) { /* Alt+ */ keycode = 0x54; } else if (down) { keyboard_input(down, 0x12a); @@ -1021,7 +1021,7 @@ MainWindow::processKeyboardInput(bool down, uint32_t keycode) break; case 0x145: /* Pause */ - if (keyboard_recv(0x1d) || keyboard_recv(0x11d)) { /* Ctrl+ */ + if (keyboard_recv_ui(0x1d) || keyboard_recv_ui(0x11d)) { /* Ctrl+ */ keycode = 0x146; } else { keyboard_input(down, 0xe11d); @@ -1195,6 +1195,8 @@ MainWindow::on_actionFullscreen_triggered() ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); showFullScreen(); } + fs_on_signal = false; + fs_off_signal = false; ui->stackedWidget->onResize(width(), height()); } @@ -1217,7 +1219,7 @@ MainWindow::getTitle(wchar_t *title) bool MainWindow::eventFilter(QObject *receiver, QEvent *event) { - if (!dopause && (mouse_capture || !kbd_req_capture)) { + if (!dopause) { if (event->type() == QEvent::Shortcut) { auto shortcutEvent = (QShortcutEvent *) event; if (shortcutEvent->key() == ui->actionExit->shortcut()) { @@ -1266,13 +1268,20 @@ MainWindow::showMessage(int flags, const QString &header, const QString &message if (QThread::currentThread() == this->thread()) { showMessage_(flags, header, message); } else { - emit showMessageForNonQtThread(flags, header, message); + std::atomic_bool done = false; + emit showMessageForNonQtThread(flags, header, message, &done); + while (!done) { + QThread::msleep(1); + } } } void -MainWindow::showMessage_(int flags, const QString &header, const QString &message) +MainWindow::showMessage_(int flags, const QString &header, const QString &message, std::atomic_bool *done) { + if (done) { + *done = false; + } QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this); if (flags & (MBX_FATAL)) { box.setIcon(QMessageBox::Critical); @@ -1281,6 +1290,9 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag } box.setTextFormat(Qt::TextFormat::RichText); box.exec(); + if (done) { + *done = true; + } if (cpu_thread_run == 0) QApplication::exit(-1); } @@ -1288,7 +1300,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag void MainWindow::keyPressEvent(QKeyEvent *event) { - if (send_keyboard_input && !(kbd_req_capture && !mouse_capture)) { + if (send_keyboard_input) { #ifdef Q_OS_MACOS processMacKeyboardInput(true, event); #else @@ -1301,10 +1313,10 @@ MainWindow::keyPressEvent(QKeyEvent *event) if (keyboard_ismsexit()) plat_mouse_capture(0); - if ((video_fullscreen > 0) && (keyboard_recv(0x1D) || keyboard_recv(0x11D))) { - if (keyboard_recv(0x57)) + if ((video_fullscreen > 0) && (keyboard_recv_ui(0x1D) || keyboard_recv_ui(0x11D))) { + if (keyboard_recv_ui(0x57)) ui->actionTake_screenshot->trigger(); - else if (keyboard_recv(0x58)) + else if (keyboard_recv_ui(0x58)) pc_send_cad(); } @@ -1327,7 +1339,7 @@ void MainWindow::keyReleaseEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Pause) { - if (keyboard_recv(0x38) && keyboard_recv(0x138)) { + if (keyboard_recv_ui(0x38) && keyboard_recv_ui(0x138)) { plat_pause(dopause ^ 1); } } @@ -1892,6 +1904,13 @@ MainWindow::updateUiPauseState() ui->actionPause->setToolTip(tooltip_text); } +void +MainWindow::updateStatusEmptyIcons() +{ + if (status != nullptr) + status->refreshEmptyIcons(); +} + void MainWindow::on_actionPreferences_triggered() { diff --git a/src/qt/qt_mainwindow.hpp b/src/qt/qt_mainwindow.hpp index 1fca092318..9db4280516 100644 --- a/src/qt/qt_mainwindow.hpp +++ b/src/qt/qt_mainwindow.hpp @@ -8,6 +8,7 @@ #include #include +#include class MediaMenu; class RendererStack; @@ -54,7 +55,7 @@ class MainWindow : public QMainWindow { void setFullscreen(bool state); void setMouseCapture(bool state); - void showMessageForNonQtThread(int flags, const QString &header, const QString &message); + void showMessageForNonQtThread(int flags, const QString &header, const QString &message, std::atomic_bool* done); void getTitleForNonQtThread(wchar_t *title); public slots: void showSettings(); @@ -62,6 +63,7 @@ public slots: void togglePause(); void initRendererMonitorSlot(int monitor_index); void destroyRendererMonitorSlot(int monitor_index); + void updateStatusEmptyIcons(); void updateUiPauseState(); private slots: void on_actionFullscreen_triggered(); @@ -120,7 +122,7 @@ private slots: void on_actionRenderer_options_triggered(); void refreshMediaMenu(); - void showMessage_(int flags, const QString &header, const QString &message); + void showMessage_(int flags, const QString &header, const QString &message, std::atomic_bool* done = nullptr); void getTitle_(wchar_t *title); void on_actionMCA_devices_triggered(); diff --git a/src/qt/qt_mainwindow.ui b/src/qt/qt_mainwindow.ui index 90dbfdab7b..b1dc0ecf1d 100644 --- a/src/qt/qt_mainwindow.ui +++ b/src/qt/qt_mainwindow.ui @@ -373,6 +373,9 @@ &Fullscreen + + Ctrl+Alt+PgUp + diff --git a/src/qt/qt_mediahistorymanager.cpp b/src/qt/qt_mediahistorymanager.cpp index 672ccfa8db..cd9be766b3 100644 --- a/src/qt/qt_mediahistorymanager.cpp +++ b/src/qt/qt_mediahistorymanager.cpp @@ -24,8 +24,15 @@ extern "C" { #include <86box/timer.h> -#include <86box/cdrom.h> +#include <86box/device.h> +#include <86box/cassette.h> +#include <86box/cartridge.h> #include <86box/fdd.h> +#include <86box/cdrom.h> +#include <86box/scsi_device.h> +#include <86box/zip.h> +#include <86box/mo.h> +#include <86box/path.h> } namespace ui { @@ -100,7 +107,14 @@ MediaHistoryManager::getImageForSlot(int index, int slot, ui::MediaType type) int MediaHistoryManager::maxDevicesSupported(ui::MediaType type) { - return type == ui::MediaType::Cassette ? 1 : 4; + switch (type) { + default: + return 4; + case ui::MediaType::Cassette: + return 1; + case ui::MediaType::Cartridge: + return 2; + } } void @@ -163,14 +177,26 @@ MediaHistoryManager::initialDeduplication() for (int device_index = 0; device_index < maxDevicesSupported(device_type); device_index++) { device_index_list_t device_history = getHistoryListForDeviceIndex(device_index, device_type); switch (device_type) { - case ui::MediaType::Optical: - current_image = cdrom[device_index].image_path; + default: + continue; + break; + case ui::MediaType::Cassette: + current_image = cassette_fname; + break; + case ui::MediaType::Cartridge: + current_image = cart_fns[device_index]; break; case ui::MediaType::Floppy: current_image = floppyfns[device_index]; break; - default: - continue; + case ui::MediaType::Optical: + current_image = cdrom[device_index].image_path; + break; + case ui::MediaType::Zip: + current_image = zip_drives[device_index].image_path; + break; + case ui::MediaType::Mo: + current_image = mo_drives[device_index].image_path; break; } deduplicateList(device_history, QVector(1, current_image)); @@ -190,12 +216,20 @@ char ** MediaHistoryManager::getEmuHistoryVarForType(ui::MediaType type, int index) { switch (type) { - case ui::MediaType::Optical: - return &cdrom[index].image_history[0]; - case ui::MediaType::Floppy: - return &fdd_image_history[index][0]; default: return nullptr; + case ui::MediaType::Cassette: + return &cassette_image_history[0]; + case ui::MediaType::Cartridge: + return &cart_image_history[index][0]; + case ui::MediaType::Floppy: + return &fdd_image_history[index][0]; + case ui::MediaType::Optical: + return &cdrom[index].image_history[0]; + case ui::MediaType::Zip: + return &zip_drives[index].image_history[0]; + case ui::MediaType::Mo: + return &mo_drives[index].image_history[0]; } } @@ -275,9 +309,6 @@ MediaHistoryManager::pathAdjustSingle(QString checked_path) if (file_info.filePath().isEmpty() || current_usr_path.isEmpty() || file_info.isRelative()) { return checked_path; } - if (file_info.filePath().startsWith(current_usr_path)) { - checked_path = file_info.filePath().remove(current_usr_path); - } return checked_path; } @@ -304,10 +335,25 @@ MediaHistoryManager::removeMissingImages(device_index_list_t &device_history) if (file_info.filePath().isEmpty()) { continue; } - // For this check, explicitly prepend `usr_path` to relative paths to account for $CWD platform variances - QFileInfo absolute_path = file_info.isRelative() ? QFileInfo(getUsrPath().append(file_info.filePath())) : file_info; - if ((file_info.filePath().left(8) != "ioctl://") && !absolute_path.exists()) { - qWarning("Image file %s does not exist - removing from history", qPrintable(file_info.filePath())); + + char *p = checked_path.toUtf8().data(); + char temp[MAX_IMAGE_PATH_LEN -1] = { 0 }; + + if (path_abs(p)) { + if (strlen(p) > (MAX_IMAGE_PATH_LEN - 1)) + fatal("removeMissingImages(): strlen(p) > 2047\n"); + else + snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s", p); + } else + snprintf(temp, (MAX_IMAGE_PATH_LEN - 1), "%s%s%s", usr_path, + path_get_slash(usr_path), p); + path_normalize(temp); + + QString qstr = QString::fromUtf8(temp); + QFileInfo new_fi(qstr); + + if ((new_fi.filePath().left(8) != "ioctl://") && !new_fi.exists()) { + qWarning("Image file %s does not exist - removing from history", qPrintable(new_fi.filePath())); checked_path = ""; } } diff --git a/src/qt/qt_mediahistorymanager.hpp b/src/qt/qt_mediahistorymanager.hpp index 4eae46f9c5..29ada8e2ac 100644 --- a/src/qt/qt_mediahistorymanager.hpp +++ b/src/qt/qt_mediahistorymanager.hpp @@ -47,7 +47,8 @@ enum class MediaType { Optical, Zip, Mo, - Cassette + Cassette, + Cartridge }; // This macro allows us to do a reverse lookup of the enum with `QMetaEnum` Q_ENUM_NS(MediaType) @@ -61,6 +62,10 @@ typedef QHash master_list_t; static const MediaType AllSupportedMediaHistoryTypes[] = { MediaType::Optical, MediaType::Floppy, + MediaType::Zip, + MediaType::Mo, + MediaType::Cassette, + MediaType::Cartridge }; class MediaHistoryManager { diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index a1d8a528c9..1fa5283d2a 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -91,6 +91,11 @@ MediaMenu::refresh(QMenu *parentMenu) cassetteMenu->addAction(tr("&Existing image..."), [this]() { cassetteSelectImage(false); }); cassetteMenu->addAction(tr("Existing image (&Write-protected)..."), [this]() { cassetteSelectImage(true); }); cassetteMenu->addSeparator(); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + cassetteImageHistoryPos[slot] = cassetteMenu->children().count(); + cassetteMenu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, slot]() { cassetteMenuSelect(slot); })->setCheckable(false); + } + cassetteMenu->addSeparator(); cassetteRecordPos = cassetteMenu->children().count(); cassetteMenu->addAction(tr("&Record"), [this] { pc_cas_set_mode(cassette, 1); cassetteUpdateMenu(); })->setCheckable(true); cassettePlayPos = cassetteMenu->children().count(); @@ -111,6 +116,11 @@ MediaMenu::refresh(QMenu *parentMenu) auto *menu = parentMenu->addMenu(""); menu->addAction(tr("&Image..."), [this, i]() { cartridgeSelectImage(i); }); menu->addSeparator(); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + cartridgeImageHistoryPos[slot] = menu->children().count(); + menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { cartridgeMenuSelect(i, slot); })->setCheckable(false); + } + menu->addSeparator(); cartridgeEjectPos = menu->children().count(); menu->addAction(tr("E&ject"), [this, i]() { cartridgeEject(i); }); cartridgeMenus[i] = menu; @@ -144,10 +154,10 @@ MediaMenu::refresh(QMenu *parentMenu) MachineStatus::iterateCDROM([this, parentMenu](int i) { auto *menu = parentMenu->addMenu(""); cdromMutePos = menu->children().count(); - menu->addAction(QApplication::style()->standardIcon(QStyle::SP_MediaVolumeMuted), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); + menu->addAction(ProgSettings::loadIcon("/cdrom_mute.ico"), tr("&Mute"), [this, i]() { cdromMute(i); })->setCheckable(true); menu->addSeparator(); - menu->addAction(ProgSettings::loadIcon("/cdrom.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false); - menu->addAction(QApplication::style()->standardIcon(QStyle::SP_DirIcon), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false); + menu->addAction(ProgSettings::loadIcon("/cdrom_image.ico"), tr("&Image..."), [this, i]() { cdromMount(i, 0, nullptr); })->setCheckable(false); + menu->addAction(ProgSettings::loadIcon("/cdrom_folder.ico"), tr("&Folder..."), [this, i]() { cdromMount(i, 1, nullptr); })->setCheckable(false); menu->addSeparator(); for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { cdromImageHistoryPos[slot] = menu->children().count(); @@ -157,10 +167,10 @@ MediaMenu::refresh(QMenu *parentMenu) #ifdef Q_OS_WINDOWS /* Loop through each Windows drive letter and test to see if it's a CDROM */ - for (auto &letter : driveLetters) { - auto drive = QString::asprintf("%c:\\", letter).toUtf8().constData(); - if (GetDriveType(drive) == DRIVE_CDROM) - menu->addAction(QApplication::style()->standardIcon(QStyle::SP_DriveCDIcon), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter]() { cdromMount(i, 2, QString::asprintf(R"(\\.\%c:)", letter).toUtf8().constData()); })->setCheckable(false); + for (const auto &letter : driveLetters) { + auto drive = QString("%1:\\").arg(letter); + if (GetDriveType(drive.toUtf8().constData()) == DRIVE_CDROM) + menu->addAction(ProgSettings::loadIcon("/cdrom_host.ico"), tr("Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false); } menu->addSeparator(); #endif // Q_OS_WINDOWS @@ -179,10 +189,13 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addAction(tr("&Existing image..."), [this, i]() { zipSelectImage(i, false); }); menu->addAction(tr("Existing image (&Write-protected)..."), [this, i]() { zipSelectImage(i, true); }); menu->addSeparator(); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + zipImageHistoryPos[slot] = menu->children().count(); + menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { zipReload(i, slot); })->setCheckable(false); + } + menu->addSeparator(); zipEjectPos = menu->children().count(); menu->addAction(tr("E&ject"), [this, i]() { zipEject(i); }); - zipReloadPos = menu->children().count(); - menu->addAction(tr("&Reload previous image"), [this, i]() { zipReload(i); }); zipMenus[i] = menu; zipUpdateMenu(i); }); @@ -195,10 +208,13 @@ MediaMenu::refresh(QMenu *parentMenu) menu->addAction(tr("&Existing image..."), [this, i]() { moSelectImage(i, false); }); menu->addAction(tr("Existing image (&Write-protected)..."), [this, i]() { moSelectImage(i, true); }); menu->addSeparator(); + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + moImageHistoryPos[slot] = menu->children().count(); + menu->addAction(QString::asprintf(tr("Image %i").toUtf8().constData(), slot), [this, i, slot]() { moReload(i, slot); })->setCheckable(false); + } + menu->addSeparator(); moEjectPos = menu->children().count(); menu->addAction(tr("E&ject"), [this, i]() { moEject(i); }); - moReloadPos = menu->children().count(); - menu->addAction(tr("&Reload previous image"), [this, i]() { moReload(i); }); moMenus[i] = menu; moUpdateMenu(i); }); @@ -243,9 +259,19 @@ MediaMenu::cassetteSelectImage(bool wp) cassetteMount(filename, wp); } +void +MediaMenu::cassetteMenuSelect(int slot) +{ + QString filename = mhm.getImageForSlot(0, slot, ui::MediaType::Cassette); + cassetteMount(filename.toUtf8().constData(), 0); + cassetteUpdateMenu(); + ui_sb_update_tip(SB_CASSETTE); +} + void MediaMenu::cassetteMount(const QString &filename, bool wp) { + auto previous_image = QFileInfo(cassette_fname); pc_cas_set_fname(cassette, nullptr); memset(cassette_fname, 0, sizeof(cassette_fname)); cassette_ui_writeprot = wp ? 1 : 0; @@ -257,6 +283,7 @@ MediaMenu::cassetteMount(const QString &filename, bool wp) } ui_sb_update_icon_state(SB_CASSETTE, filename.isEmpty() ? 1 : 0); + mhm.addImageToHistory(0, ui::MediaType::Cassette, previous_image.filePath(), filename); cassetteUpdateMenu(); ui_sb_update_tip(SB_CASSETTE); config_save(); @@ -265,6 +292,7 @@ MediaMenu::cassetteMount(const QString &filename, bool wp) void MediaMenu::cassetteEject() { + mhm.addImageToHistory(0, ui::MediaType::Cassette, cassette_fname, QString()); pc_cas_set_fname(cassette, nullptr); memset(cassette_fname, 0, sizeof(cassette_fname)); ui_sb_update_icon_state(SB_CASSETTE, 1); @@ -297,16 +325,22 @@ MediaMenu::cassetteUpdateMenu() cassetteMenu->setTitle(QString::asprintf(tr("Cassette: %s").toUtf8().constData(), (name.isEmpty() ? tr("(empty)") : name).toUtf8().constData())); + + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + updateImageHistory(0, slot, ui::MediaType::Cassette); + } } void MediaMenu::cartridgeMount(int i, const QString &filename) { + auto previous_image = QFileInfo(cart_fns[i]); cart_close(i); QByteArray filenameBytes = filename.toUtf8(); cart_load(i, filenameBytes.data()); ui_sb_update_icon_state(SB_CARTRIDGE | i, filename.isEmpty() ? 1 : 0); + mhm.addImageToHistory(i, ui::MediaType::Cartridge, previous_image.filePath(), filename); cartridgeUpdateMenu(i); ui_sb_update_tip(SB_CARTRIDGE | i); config_save(); @@ -327,9 +361,19 @@ MediaMenu::cartridgeSelectImage(int i) cartridgeMount(i, filename); } +void +MediaMenu::cartridgeMenuSelect(int index, int slot) +{ + QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Cartridge); + cartridgeMount(index, filename.toUtf8().constData()); + cartridgeUpdateMenu(index); + ui_sb_update_tip(SB_CARTRIDGE | index); +} + void MediaMenu::cartridgeEject(int i) { + mhm.addImageToHistory(i, ui::MediaType::Cartridge, cart_fns[i], QString()); cart_close(i); ui_sb_update_icon_state(SB_CARTRIDGE | i, 1); cartridgeUpdateMenu(i); @@ -347,6 +391,10 @@ MediaMenu::cartridgeUpdateMenu(int i) ejectMenu->setEnabled(!name.isEmpty()); // menu->setTitle(tr("Cartridge %1: %2").arg(QString::number(i+1), name.isEmpty() ? tr("(empty)") : name)); menu->setTitle(QString::asprintf(tr("Cartridge %i: %ls").toUtf8().constData(), i + 1, name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) { + updateImageHistory(i, slot, ui::MediaType::Cartridge); + } } void @@ -478,11 +526,8 @@ MediaMenu::cdromMount(int i, const QString &filename) { QByteArray fn = filename.toUtf8().data(); - strcpy(cdrom[i].prev_image_path, cdrom[i].image_path); - if (cdrom[i].ops && cdrom[i].ops->exit) - cdrom[i].ops->exit(&(cdrom[i])); + cdrom_exit(i); - cdrom[i].ops = nullptr; memset(cdrom[i].image_path, 0, sizeof(cdrom[i].image_path)); #ifdef Q_OS_WINDOWS if ((fn.data() != nullptr) && (strlen(fn.data()) >= 1) && (fn.data()[strlen(fn.data()) - 1] == '/')) @@ -495,6 +540,7 @@ MediaMenu::cdromMount(int i, const QString &filename) cdrom_ioctl_open(&(cdrom[i]), fn.data()); else cdrom_image_open(&(cdrom[i]), fn.data()); + /* Signal media change to the emulated machine. */ if (cdrom[i].insert) cdrom[i].insert(cdrom[i].priv); @@ -580,6 +626,36 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) QString menu_item_name; switch (type) { + default: + menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + return; + case ui::MediaType::Cassette: + if (!MachineStatus::hasCassette()) + return; + menu = cassetteMenu; + children = menu->children(); + imageHistoryUpdatePos = dynamic_cast(children[cassetteImageHistoryPos[slot]]); + fi.setFile(fn); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + break; + case ui::MediaType::Cartridge: + if (!machine_has_cartridge(machine)) + return; + menu = cartridgeMenus[index]; + children = menu->children(); + imageHistoryUpdatePos = dynamic_cast(children[cartridgeImageHistoryPos[slot]]); + fi.setFile(fn); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + break; + case ui::MediaType::Floppy: + if (!floppyMenus.contains(index)) + return; + menu = floppyMenus[index]; + children = menu->children(); + imageHistoryUpdatePos = dynamic_cast(children[floppyImageHistoryPos[slot]]); + fi.setFile(fn); + menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); + break; case ui::MediaType::Optical: if (!cdromMenus.contains(index)) return; @@ -587,7 +663,7 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) children = menu->children(); imageHistoryUpdatePos = dynamic_cast(children[cdromImageHistoryPos[slot]]); if (fn.left(8) == "ioctl://") { - menu_icon = QApplication::style()->standardIcon(QStyle::SP_DriveCDIcon); + menu_icon = ProgSettings::loadIcon("/cdrom_host.ico"); #ifdef Q_OS_WINDOWS menu_item_name = tr("Host CD/DVD Drive (%1)").arg(fn.right(2)).toUtf8().constData(); #else @@ -595,23 +671,29 @@ MediaMenu::updateImageHistory(int index, int slot, ui::MediaType type) #endif } else { fi.setFile(fn); - menu_icon = fi.isDir() ? QApplication::style()->standardIcon(QStyle::SP_DirIcon) : ProgSettings::loadIcon("/cdrom.ico"); + menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico"); menu_item_name = fn.isEmpty() ? tr("previous image").toUtf8().constData() : fn.toUtf8().constData(); } imageHistoryUpdatePos->setIcon(menu_icon); break; - case ui::MediaType::Floppy: - if (!floppyMenus.contains(index)) + case ui::MediaType::Zip: + if (!zipMenus.contains(index)) return; - menu = floppyMenus[index]; + menu = zipMenus[index]; children = menu->children(); - imageHistoryUpdatePos = dynamic_cast(children[floppyImageHistoryPos[slot]]); + imageHistoryUpdatePos = dynamic_cast(children[zipImageHistoryPos[slot]]); fi.setFile(fn); menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); break; - default: + case ui::MediaType::Mo: + if (!moMenus.contains(index)) + return; + menu = moMenus[index]; + children = menu->children(); + imageHistoryUpdatePos = dynamic_cast(children[moImageHistoryPos[slot]]); + fi.setFile(fn); menu_item_name = fi.fileName().isEmpty() ? tr("previous image").toUtf8().constData() : fi.fileName().toUtf8().constData(); - return; + break; } imageHistoryUpdatePos->setText(QString::asprintf(tr("%s").toUtf8().constData(), menu_item_name.toUtf8().constData())); @@ -642,7 +724,7 @@ MediaMenu::cdromUpdateMenu(int i) auto childs = menu->children(); auto *muteMenu = dynamic_cast(childs[cdromMutePos]); - muteMenu->setIcon(QApplication::style()->standardIcon((cdrom[i].sound_on == 0) ? QStyle::SP_MediaVolume : QStyle::SP_MediaVolumeMuted)); + muteMenu->setIcon(ProgSettings::loadIcon((cdrom[i].sound_on == 0) ? "/cdrom_unmute.ico" : "/cdrom_mute.ico")); muteMenu->setText((cdrom[i].sound_on == 0) ? tr("&Unmute") : tr("&Mute")); auto *imageMenu = dynamic_cast(childs[cdromImagePos]); @@ -655,13 +737,13 @@ MediaMenu::cdromUpdateMenu(int i) menu_item_name = tr("Host CD/DVD Drive (%1)").arg(name.right(name.length() - 8)); #endif name2 = menu_item_name; - menu_icon = QApplication::style()->standardIcon(QStyle::SP_DriveCDIcon); + menu_icon = ProgSettings::loadIcon("/cdrom_host.ico"); } else { QFileInfo fi(cdrom[i].image_path); menu_item_name = name.isEmpty() ? QString().toUtf8().constData() : name.toUtf8().constData(); name2 = name; - menu_icon = fi.isDir() ? QApplication::style()->standardIcon(QStyle::SP_DirIcon) : ProgSettings::loadIcon("/cdrom.ico"); + menu_icon = fi.isDir() ? ProgSettings::loadIcon("/cdrom_folder.ico") : ProgSettings::loadIcon("/cdrom_image.ico"); } imageMenu->setIcon(menu_icon); imageMenu->setText(QString::asprintf(tr("Eject %s").toUtf8().constData(), menu_item_name.toUtf8().constData())); @@ -727,6 +809,7 @@ MediaMenu::zipMount(int i, const QString &filename, bool wp) zip_load(dev, filenameBytes.data()); zip_insert(dev); } + mhm.addImageToHistory(i, ui::MediaType::Zip, zip_drives[i].prev_image_path, zip_drives[i].image_path); ui_sb_update_icon_state(SB_ZIP | i, filename.isEmpty() ? 1 : 0); zipUpdateMenu(i); @@ -740,6 +823,7 @@ MediaMenu::zipEject(int i) { const auto dev = static_cast(zip_drives[i].priv); + mhm.addImageToHistory(i, ui::MediaType::Zip, zip_drives[i].image_path, QString()); zip_disk_close(dev); zip_drives[i].image_path[0] = 0; if (zip_drives[i].bus_type) { @@ -754,7 +838,7 @@ MediaMenu::zipEject(int i) } void -MediaMenu::zipReload(int i) +MediaMenu::zipReloadPrev(int i) { const auto dev = static_cast(zip_drives[i].priv); @@ -771,6 +855,15 @@ MediaMenu::zipReload(int i) config_save(); } +void +MediaMenu::zipReload(int index, int slot) +{ + const QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Zip); + zipMount(index, filename, false); + zipUpdateMenu(index); + ui_sb_update_tip(SB_ZIP | index); +} + void MediaMenu::zipUpdateMenu(int i) { @@ -782,9 +875,7 @@ MediaMenu::zipUpdateMenu(int i) auto childs = menu->children(); auto *ejectMenu = dynamic_cast(childs[zipEjectPos]); - auto *reloadMenu = dynamic_cast(childs[zipReloadPos]); ejectMenu->setEnabled(!name.isEmpty()); - reloadMenu->setEnabled(!prev_name.isEmpty()); QString busName = tr("Unknown Bus"); switch (zip_drives[i].bus_type) { @@ -800,6 +891,9 @@ MediaMenu::zipUpdateMenu(int i) // menu->setTitle(tr("ZIP %1 %2 (%3): %4").arg((zip_drives[i].is_250 > 0) ? "250" : "100", QString::number(i+1), busName, name.isEmpty() ? tr("(empty)") : name)); menu->setTitle(QString::asprintf(tr("ZIP %03i %i (%s): %ls").toUtf8().constData(), (zip_drives[i].is_250 > 0) ? 250 : 100, i + 1, busName.toUtf8().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) + updateImageHistory(i, slot, ui::MediaType::Zip); } void @@ -844,6 +938,7 @@ MediaMenu::moMount(int i, const QString &filename, bool wp) mo_load(dev, filenameBytes.data()); mo_insert(dev); } + mhm.addImageToHistory(i, ui::MediaType::Mo, mo_drives[i].prev_image_path, mo_drives[i].image_path); ui_sb_update_icon_state(SB_MO | i, filename.isEmpty() ? 1 : 0); moUpdateMenu(i); @@ -857,6 +952,7 @@ MediaMenu::moEject(int i) { const auto dev = static_cast(mo_drives[i].priv); + mhm.addImageToHistory(i, ui::MediaType::Mo, mo_drives[i].image_path, QString()); mo_disk_close(dev); mo_drives[i].image_path[0] = 0; if (mo_drives[i].bus_type) { @@ -871,7 +967,7 @@ MediaMenu::moEject(int i) } void -MediaMenu::moReload(int i) +MediaMenu::moReloadPrev(int i) { mo_t *dev = (mo_t *) mo_drives[i].priv; @@ -888,6 +984,15 @@ MediaMenu::moReload(int i) config_save(); } +void +MediaMenu::moReload(int index, int slot) +{ + const QString filename = mhm.getImageForSlot(index, slot, ui::MediaType::Mo); + moMount(index, filename, false); + moUpdateMenu(index); + ui_sb_update_tip(SB_MO | index); +} + void MediaMenu::moUpdateMenu(int i) { @@ -899,9 +1004,7 @@ MediaMenu::moUpdateMenu(int i) auto childs = menu->children(); auto *ejectMenu = dynamic_cast(childs[moEjectPos]); - auto *reloadMenu = dynamic_cast(childs[moReloadPos]); ejectMenu->setEnabled(!name.isEmpty()); - reloadMenu->setEnabled(!prev_name.isEmpty()); QString busName = tr("Unknown Bus"); switch (mo_drives[i].bus_type) { @@ -916,6 +1019,9 @@ MediaMenu::moUpdateMenu(int i) } menu->setTitle(QString::asprintf(tr("MO %i (%ls): %ls").toUtf8().constData(), i + 1, busName.toStdU16String().data(), name.isEmpty() ? tr("(empty)").toStdU16String().data() : name.toStdU16String().data())); + + for (int slot = 0; slot < MAX_PREV_IMAGES; slot++) + updateImageHistory(i, slot, ui::MediaType::Mo); } void @@ -1043,7 +1149,7 @@ zip_mount(uint8_t id, char *fn, uint8_t wp) void zip_reload(uint8_t id) { - MediaMenu::ptr->zipReload(id); + MediaMenu::ptr->zipReloadPrev(id); } void @@ -1061,6 +1167,6 @@ mo_mount(uint8_t id, char *fn, uint8_t wp) void mo_reload(uint8_t id) { - MediaMenu::ptr->moReload(id); + MediaMenu::ptr->moReloadPrev(id); } } diff --git a/src/qt/qt_mediamenu.hpp b/src/qt/qt_mediamenu.hpp index 725ce92b37..b069c67d91 100644 --- a/src/qt/qt_mediamenu.hpp +++ b/src/qt/qt_mediamenu.hpp @@ -24,12 +24,14 @@ class MediaMenu : public QObject { void cassetteNewImage(); void cassetteSelectImage(bool wp); void cassetteMount(const QString &filename, bool wp); + void cassetteMenuSelect(int slot); void cassetteEject(); void cassetteUpdateMenu(); void cartridgeSelectImage(int i); void cartridgeMount(int i, const QString &filename); void cartridgeEject(int i); + void cartridgeMenuSelect(int index, int slot); void cartridgeUpdateMenu(int i); void floppyNewImage(int i); @@ -53,14 +55,16 @@ class MediaMenu : public QObject { void zipSelectImage(int i, bool wp); void zipMount(int i, const QString &filename, bool wp); void zipEject(int i); - void zipReload(int i); + void zipReloadPrev(int i); + void zipReload(int index, int slot); void zipUpdateMenu(int i); void moNewImage(int i); void moSelectImage(int i, bool wp); void moMount(int i, const QString &filename, bool wp); void moEject(int i); - void moReload(int i); + void moReloadPrev(int i); + void moReload(int index, int slot); void moUpdateMenu(int i); void nicConnect(int i); @@ -94,24 +98,25 @@ public slots: int cassetteRewindPos; int cassetteFastFwdPos; int cassetteEjectPos; + int cassetteImageHistoryPos[MAX_PREV_IMAGES]; int cartridgeEjectPos; + int cartridgeImageHistoryPos[MAX_PREV_IMAGES]; int floppyExportPos; int floppyEjectPos; + int floppyImageHistoryPos[MAX_PREV_IMAGES]; int cdromMutePos; - int cdromReloadPos; int cdromImagePos; int cdromDirPos; int cdromImageHistoryPos[MAX_PREV_IMAGES]; - int floppyImageHistoryPos[MAX_PREV_IMAGES]; int zipEjectPos; - int zipReloadPos; + int zipImageHistoryPos[MAX_PREV_IMAGES]; int moEjectPos; - int moReloadPos; + int moImageHistoryPos[MAX_PREV_IMAGES]; int netDisconnPos; diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index edfefa39f9..e48cb1f3e3 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -54,6 +54,10 @@ # include #endif +#ifdef Q_OS_OPENBSD +# include +#endif + #if 0 static QByteArray buf; #endif @@ -227,7 +231,12 @@ plat_getcwd(char *bufp, int max) { #ifdef __APPLE__ /* Working directory for .app bundles is undefined. */ +#ifdef USE_EXE_PATH strncpy(bufp, exe_path, max); +#else + CharPointer(bufp, max) = QDir::homePath().toUtf8(); + path_append_filename(bufp, bufp, "Library/86Box"); +#endif #else CharPointer(bufp, max) = QDir::currentPath().toUtf8(); #endif @@ -585,14 +594,17 @@ c16stombs(char dst[], const uint16_t src[], int len) #ifdef _WIN32 # if defined(__amd64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64) -# define LIB_NAME_GS "gsdll64.dll" +# define LIB_NAME_GS "gsdll64.dll" +# define LIB_NAME_GPCL "gpcl6dll64.dll" # else -# define LIB_NAME_GS "gsdll32.dll" +# define LIB_NAME_GS "gsdll32.dll" +# define LIB_NAME_GPCL "gpcl6dll32.dll" # endif # define LIB_NAME_PCAP "Npcap" # define MOUSE_CAPTURE_KEYSEQ "F8+F12" #else # define LIB_NAME_GS "libgs" +# define LIB_NAME_GPCL "libgpcl6" # define LIB_NAME_PCAP "libpcap" # define MOUSE_CAPTURE_KEYSEQ "Ctrl+End" #endif @@ -613,6 +625,8 @@ ProgSettings::reloadStrings() translatedstrings[STRING_PCAP_ERROR_DESC] = QCoreApplication::translate("", "Make sure %1 is installed and that you are on a %1-compatible network connection.").arg(LIB_NAME_PCAP).toStdWString(); translatedstrings[STRING_GHOSTSCRIPT_ERROR_TITLE] = QCoreApplication::translate("", "Unable to initialize Ghostscript").toStdWString(); translatedstrings[STRING_GHOSTSCRIPT_ERROR_DESC] = QCoreApplication::translate("", "%1 is required for automatic conversion of PostScript files to PDF.\n\nAny documents sent to the generic PostScript printer will be saved as PostScript (.ps) files.").arg(LIB_NAME_GS).toStdWString(); + translatedstrings[STRING_GHOSTPCL_ERROR_TITLE] = QCoreApplication::translate("", "Unable to initialize GhostPCL").toStdWString(); + translatedstrings[STRING_GHOSTPCL_ERROR_DESC] = QCoreApplication::translate("", "%1 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files.").arg(LIB_NAME_GPCL).toStdWString(); translatedstrings[STRING_HW_NOT_AVAILABLE_MACHINE] = QCoreApplication::translate("", "Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine.").toStdWString(); translatedstrings[STRING_HW_NOT_AVAILABLE_VIDEO] = QCoreApplication::translate("", "Video card \"%hs\" is not available due to missing ROMs in the roms/video directory. Switching to an available video card.").toStdWString(); translatedstrings[STRING_HW_NOT_AVAILABLE_VIDEO2] = QCoreApplication::translate("", "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.").toStdWString(); @@ -794,8 +808,10 @@ plat_set_thread_name(void *thread, const char *name) char truncated[16]; # endif strncpy(truncated, name, sizeof(truncated) - 1); -# ifdef Q_OS_DARWIN +# if defined(Q_OS_DARWIN) pthread_setname_np(truncated); +# elif defined(Q_OS_OPENBSD) + pthread_set_name_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # else pthread_setname_np(thread ? *((pthread_t *) thread) : pthread_self(), truncated); # endif diff --git a/src/qt/qt_progsettings.cpp b/src/qt/qt_progsettings.cpp index 2d047a7876..4e53b28188 100644 --- a/src/qt/qt_progsettings.cpp +++ b/src/qt/qt_progsettings.cpp @@ -159,16 +159,18 @@ ProgSettings::on_pushButton_released() QString ProgSettings::getFontName(uint32_t lcid) { - if (lcid == 0x0804) /* zh-CN */ - return "Microsoft YaHei"; - else if (lcid == 0x0404) /* zh-TW */ + switch (lcid) { + case 0x0404: /* zh-TW */ return "Microsoft JhengHei"; - else if (lcid == 0x0411) /* ja-JP */ + case 0x0411: /* ja-JP */ return "Meiryo UI"; - else if (lcid == 0x0412) /* ko-KR */ + case 0x0412: /* ko-KR */ return "Malgun Gothic"; - else + case 0x0804: /* zh-CN */ + return "Microsoft YaHei"; + default: return "Segoe UI"; + } } #endif diff --git a/src/qt/qt_progsettings.ui b/src/qt/qt_progsettings.ui index 16fb439be9..ac43273417 100644 --- a/src/qt/qt_progsettings.ui +++ b/src/qt/qt_progsettings.ui @@ -88,7 +88,7 @@ - + 10 diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index bc4cb9c133..fd22b5173a 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -114,7 +114,8 @@ RendererStack::RendererStack(QWidget *parent, int monitor_index) RendererStack::~RendererStack() { - QApplication::restoreOverrideCursor(); + while (QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); delete ui; } @@ -123,7 +124,7 @@ qt_mouse_capture(int on) { if (!on) { mouse_capture = 0; - if (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); + while (QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); #ifdef __APPLE__ CGAssociateMouseAndMouseCursorPosition(true); #endif @@ -199,7 +200,11 @@ RendererStack::mousePressEvent(QMouseEvent *event) void RendererStack::wheelEvent(QWheelEvent *event) { - mouse_set_z(event->pixelDelta().y()); + double numSteps = (double) event->angleDelta().y() / 120.0; + + mouse_set_z((int) numSteps); + + event->accept(); } void @@ -247,10 +252,12 @@ RendererStack::enterEvent(QEnterEvent *event) RendererStack::enterEvent(QEvent *event) #endif { - mousedata.mouse_tablet_in_proximity = 1; + mousedata.mouse_tablet_in_proximity = m_monitor_index + 1; if (mouse_input_mode == 1) QApplication::setOverrideCursor(Qt::BlankCursor); + else if (mouse_input_mode == 2) + QApplication::setOverrideCursor(Qt::CrossCursor); } void @@ -258,8 +265,10 @@ RendererStack::leaveEvent(QEvent *event) { mousedata.mouse_tablet_in_proximity = 0; - if (mouse_input_mode == 1 && QApplication::overrideCursor()) - QApplication::restoreOverrideCursor(); + if (mouse_input_mode == 1 && QApplication::overrideCursor()) { + while (QApplication::overrideCursor()) + QApplication::restoreOverrideCursor(); + } if (QApplication::platformName().contains("wayland")) { event->accept(); return; diff --git a/src/qt/qt_settings.cpp b/src/qt/qt_settings.cpp index e9767083ad..67064b73a1 100644 --- a/src/qt/qt_settings.cpp +++ b/src/qt/qt_settings.cpp @@ -50,6 +50,7 @@ class SettingsModel : public QAbstractListModel { SettingsModel(QObject *parent) : QAbstractListModel(parent) { + fontHeight = QApplication::fontMetrics().height(); } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; @@ -82,6 +83,7 @@ class SettingsModel : public QAbstractListModel { "other_removable_devices", "other_peripherals", }; + int fontHeight; }; QVariant @@ -94,6 +96,8 @@ SettingsModel::data(const QModelIndex &index, int role) const return tr(pages.at(index.row()).toUtf8().data()); case Qt::DecorationRole: return QIcon(QString("%1/%2.ico").arg(ProgSettings::getIconSetPath(), page_icons[index.row()])); + case Qt::SizeHintRole: + return QSize(-1, fontHeight * 2); default: return {}; } @@ -182,9 +186,6 @@ Settings::Settings(QWidget *parent) [this](const QModelIndex ¤t, const QModelIndex &previous) { ui->stackedWidget->setCurrentIndex(current.row()); }); - ui->listView->setMinimumWidth(ui->listView->sizeHintForColumn(0) + - qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent)); - ui->listView->setCurrentIndex(model->index(0, 0)); Settings::settings = this; diff --git a/src/qt/qt_settings.ui b/src/qt/qt_settings.ui index 7b4d28bec9..da31b98c4a 100644 --- a/src/qt/qt_settings.ui +++ b/src/qt/qt_settings.ui @@ -37,9 +37,30 @@ + + + 0 + 0 + + + + + 200 + 0 + + + + + 200 + 16777215 + + QListView::ListMode + + true + diff --git a/src/qt/qt_settingsdisplay.cpp b/src/qt/qt_settingsdisplay.cpp index 6969a1c2c4..db8c30e5d6 100644 --- a/src/qt/qt_settingsdisplay.cpp +++ b/src/qt/qt_settingsdisplay.cpp @@ -36,8 +36,8 @@ SettingsDisplay::SettingsDisplay(QWidget *parent) { ui->setupUi(this); - videoCard[0] = gfxcard[0]; - videoCard[1] = gfxcard[1]; + for (uint8_t i = 0; i < GFXCARD_MAX; i ++) + videoCard[i] = gfxcard[i]; onCurrentMachineChanged(machine); } @@ -50,7 +50,9 @@ void SettingsDisplay::save() { gfxcard[0] = ui->comboBoxVideo->currentData().toInt(); - gfxcard[1] = ui->comboBoxVideoSecondary->currentData().toInt(); + // TODO + for (uint8_t i = 1; i < GFXCARD_MAX; i ++) + gfxcard[i] = ui->comboBoxVideoSecondary->currentData().toInt(); voodoo_enabled = ui->checkBoxVoodoo->isChecked() ? 1 : 0; ibm8514_standalone_enabled = ui->checkBox8514->isChecked() ? 1 : 0; xga_standalone_enabled = ui->checkBoxXga->isChecked() ? 1 : 0; @@ -103,8 +105,10 @@ SettingsDisplay::onCurrentMachineChanged(int machineId) ui->pushButtonConfigureSecondary->setEnabled(true); } ui->comboBoxVideo->setCurrentIndex(selectedRow); - if (gfxcard[1] == 0) - ui->pushButtonConfigureSecondary->setEnabled(false); + // TODO + for (uint8_t i = 1; i < GFXCARD_MAX; i ++) + if (gfxcard[i] == 0) + ui->pushButtonConfigureSecondary->setEnabled(false); } void diff --git a/src/qt/qt_settingsdisplay.hpp b/src/qt/qt_settingsdisplay.hpp index 8331bbb5b9..6297f7eae5 100644 --- a/src/qt/qt_settingsdisplay.hpp +++ b/src/qt/qt_settingsdisplay.hpp @@ -3,6 +3,8 @@ #include +#define VIDEOCARD_MAX 2 + namespace Ui { class SettingsDisplay; } @@ -36,7 +38,7 @@ private slots: private: Ui::SettingsDisplay *ui; int machineId = 0; - int videoCard[2] = { 0, 0 }; + int videoCard[VIDEOCARD_MAX] = { 0, 0 }; }; #endif // QT_SETTINGSDISPLAY_HPP diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index 8f0ac81a9c..190dbc2e1f 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -218,7 +218,6 @@ SettingsFloppyCDROM::save() /* Removable devices category */ model = ui->tableViewCDROM->model(); for (int i = 0; i < CDROM_NUM; i++) { - cdrom[i].is_dir = 0; cdrom[i].priv = NULL; cdrom[i].ops = NULL; cdrom[i].image = NULL; diff --git a/src/qt/qt_settingsfloppycdrom.ui b/src/qt/qt_settingsfloppycdrom.ui index d7ad853b38..b9a937d8df 100644 --- a/src/qt/qt_settingsfloppycdrom.ui +++ b/src/qt/qt_settingsfloppycdrom.ui @@ -7,7 +7,7 @@ 0 0 544 - 617 + 363 @@ -35,6 +35,18 @@ + + + 0 + 0 + + + + + 16777215 + 150 + + QAbstractItemView::NoEditTriggers @@ -53,49 +65,38 @@ - - - - - Type: - - - - - - - 30 - - - - - - - Turbo timings - - - - - - - Check BPB - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - + + + + + + Type: + + + + + + + 30 + + + + + + + Turbo timings + + + + + + + Check BPB + + + + + @@ -106,6 +107,18 @@ + + + 0 + 0 + + + + + 16777215 + 150 + + QAbstractItemView::NoEditTriggers @@ -124,64 +137,66 @@ - - - - - Bus: - - - - - - - Channel: - - - - - - - Speed: - - - - - - - Type: - - - - - - - 30 - - - - - - - 30 - - - - - - - 30 - - - - - - - 30 - - - - + + + + + + Bus: + + + + + + + Channel: + + + + + + + Speed: + + + + + + + Type: + + + + + + + 30 + + + + + + + 30 + + + + + + + 30 + + + + + + + 30 + + + + + diff --git a/src/qt/qt_settingsmachine.cpp b/src/qt/qt_settingsmachine.cpp index aff55203e8..771f1cbec1 100644 --- a/src/qt/qt_settingsmachine.cpp +++ b/src/qt/qt_settingsmachine.cpp @@ -61,7 +61,7 @@ SettingsMachine::SettingsMachine(QWidget *parent) break; } - auto warning_icon = ui->softFloatWarningIcon->style()->standardIcon(QStyle::SP_MessageBoxWarning); + auto warning_icon = QIcon(":/misc/qt/icons/warning.ico"); ui->softFloatWarningIcon->setPixmap(warning_icon.pixmap(warning_icon.actualSize(QSize(16, 16)))); ui->softFloatWarningIcon->setVisible(false); ui->softFloatWarningText->setVisible(false); @@ -301,7 +301,7 @@ SettingsMachine::on_comboBoxSpeed_currentIndexChanged(int index) for (const char *fpuName = fpu_get_name_from_index(cpuFamily, cpuId, i); fpuName != nullptr; fpuName = fpu_get_name_from_index(cpuFamily, cpuId, ++i)) { auto fpuType = fpu_get_type_from_index(cpuFamily, cpuId, i); - Models::AddEntry(modelFpu, QString("%1").arg(fpuName), fpuType); + Models::AddEntry(modelFpu, tr(QString("%1").arg(fpuName).toUtf8().data()), fpuType); if (fpu_type == fpuType) selectedFpuRow = i; } diff --git a/src/qt/qt_settingsotherperipherals.cpp b/src/qt/qt_settingsotherperipherals.cpp index 3904b653ab..a7db551ad8 100644 --- a/src/qt/qt_settingsotherperipherals.cpp +++ b/src/qt/qt_settingsotherperipherals.cpp @@ -81,6 +81,7 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) ++d; } ui->comboBoxRTC->setCurrentIndex(selectedRow); + ui->pushButtonConfigureRTC->setEnabled((isartc_type != 0) && isartc_has_config(isartc_type) && machineHasIsa); for (int c = 0; c < ISAMEM_MAX; c++) { auto *cbox = findChild(QString("comboBoxCard%1").arg(c + 1)); @@ -106,7 +107,7 @@ SettingsOtherPeripherals::onCurrentMachineChanged(int machineId) cbox->setCurrentIndex(-1); cbox->setCurrentIndex(selectedRow); cbox->setEnabled(machineHasIsa); - findChild(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled(isamem_type[c] != 0 && machineHasIsa); + findChild(QString("pushButtonConfigureCard%1").arg(c + 1))->setEnabled((isamem_type[c] != 0) && isamem_has_config(isamem_type[c]) && machineHasIsa); } } @@ -138,7 +139,7 @@ SettingsOtherPeripherals::on_comboBoxRTC_currentIndexChanged(int index) if (index < 0) { return; } - ui->pushButtonConfigureRTC->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); + ui->pushButtonConfigureRTC->setEnabled((index != 0) && isartc_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void @@ -153,7 +154,7 @@ SettingsOtherPeripherals::on_comboBoxCard1_currentIndexChanged(int index) if (index < 0) { return; } - ui->pushButtonConfigureCard1->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); + ui->pushButtonConfigureCard1->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void @@ -168,7 +169,7 @@ SettingsOtherPeripherals::on_comboBoxCard2_currentIndexChanged(int index) if (index < 0) { return; } - ui->pushButtonConfigureCard2->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); + ui->pushButtonConfigureCard2->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void @@ -183,7 +184,7 @@ SettingsOtherPeripherals::on_comboBoxCard3_currentIndexChanged(int index) if (index < 0) { return; } - ui->pushButtonConfigureCard3->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); + ui->pushButtonConfigureCard3->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void @@ -198,7 +199,7 @@ SettingsOtherPeripherals::on_comboBoxCard4_currentIndexChanged(int index) if (index < 0) { return; } - ui->pushButtonConfigureCard4->setEnabled(index != 0 && machine_has_bus(machineId, MACHINE_BUS_ISA)); + ui->pushButtonConfigureCard4->setEnabled((index != 0) && isamem_has_config(index) && machine_has_bus(machineId, MACHINE_BUS_ISA)); } void diff --git a/src/qt/qt_settingsotherremovable.ui b/src/qt/qt_settingsotherremovable.ui index 219333376c..8962184fc1 100644 --- a/src/qt/qt_settingsotherremovable.ui +++ b/src/qt/qt_settingsotherremovable.ui @@ -7,7 +7,7 @@ 0 0 418 - 433 + 368 @@ -35,6 +35,18 @@ + + + 0 + 0 + + + + + 16777215 + 150 + + QAbstractItemView::NoEditTriggers @@ -53,63 +65,52 @@ - - - - - Bus: - - - - - - - Channel: - - - - - - - 30 - - - - - - - 30 - - - - - - - Type: - - - - - - - 30 - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - + + + + + + Bus: + + + + + + + Channel: + + + + + + + 30 + + + + + + + 30 + + + + + + + Type: + + + + + + + 30 + + + + + @@ -120,6 +121,18 @@ + + + 0 + 0 + + + + + 16777215 + 150 + + QAbstractItemView::NoEditTriggers @@ -138,43 +151,45 @@ - - - - - Bus: - - - - - - - 30 - - - - - - - Channel: - - - - - - - 30 - - - - - - - ZIP 250 - - - - + + + + + + Bus: + + + + + + + 30 + + + + + + + Channel: + + + + + + + 30 + + + + + + + ZIP 250 + + + + + diff --git a/src/qt/qt_settingsports.cpp b/src/qt/qt_settingsports.cpp index 9b19df68df..01d7d3f9f9 100644 --- a/src/qt/qt_settingsports.cpp +++ b/src/qt/qt_settingsports.cpp @@ -59,23 +59,30 @@ SettingsPorts::SettingsPorts(QWidget *parent) cbox->setCurrentIndex(selectedRow); auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); - checkBox->setChecked(lpt_ports[i].enabled > 0); - cbox->setEnabled(lpt_ports[i].enabled > 0); + if (checkBox != NULL) + checkBox->setChecked(lpt_ports[i].enabled > 0); + if (cbox != NULL) + cbox->setEnabled(lpt_ports[i].enabled > 0); } for (int i = 0; i < SERIAL_MAX; i++) { - auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); - checkBox->setChecked(com_ports[i].enabled > 0); + auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); + auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); + if (checkBox != NULL) + checkBox->setChecked(com_ports[i].enabled > 0); + if (checkBoxPass != NULL) + checkBoxPass->setChecked(serial_passthrough_enabled[i]); } - ui->checkBoxSerialPassThru1->setChecked(serial_passthrough_enabled[0]); ui->pushButtonSerialPassThru1->setEnabled(serial_passthrough_enabled[0]); - ui->checkBoxSerialPassThru2->setChecked(serial_passthrough_enabled[1]); ui->pushButtonSerialPassThru2->setEnabled(serial_passthrough_enabled[1]); - ui->checkBoxSerialPassThru3->setChecked(serial_passthrough_enabled[2]); ui->pushButtonSerialPassThru3->setEnabled(serial_passthrough_enabled[2]); - ui->checkBoxSerialPassThru4->setChecked(serial_passthrough_enabled[3]); ui->pushButtonSerialPassThru4->setEnabled(serial_passthrough_enabled[3]); +#if 0 + ui->pushButtonSerialPassThru5->setEnabled(serial_passthrough_enabled[4]); + ui->pushButtonSerialPassThru6->setEnabled(serial_passthrough_enabled[5]); + ui->pushButtonSerialPassThru7->setEnabled(serial_passthrough_enabled[6]); +#endif } SettingsPorts::~SettingsPorts() @@ -87,21 +94,22 @@ void SettingsPorts::save() { for (int i = 0; i < PARALLEL_MAX; i++) { - auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); + auto *cbox = findChild(QString("comboBoxLpt%1").arg(i + 1)); auto *checkBox = findChild(QString("checkBoxParallel%1").arg(i + 1)); - lpt_ports[i].device = cbox->currentData().toInt(); - lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + if (cbox != NULL) + lpt_ports[i].device = cbox->currentData().toInt(); + if (checkBox != NULL) + lpt_ports[i].enabled = checkBox->isChecked() ? 1 : 0; } for (int i = 0; i < SERIAL_MAX; i++) { - auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); - com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + auto *checkBox = findChild(QString("checkBoxSerial%1").arg(i + 1)); + auto *checkBoxPass = findChild(QString("checkBoxSerialPassThru%1").arg(i + 1)); + if (checkBox != NULL) + com_ports[i].enabled = checkBox->isChecked() ? 1 : 0; + if (checkBoxPass != NULL) + serial_passthrough_enabled[i] = checkBoxPass->isChecked(); } - - serial_passthrough_enabled[0] = ui->checkBoxSerialPassThru1->isChecked(); - serial_passthrough_enabled[1] = ui->checkBoxSerialPassThru2->isChecked(); - serial_passthrough_enabled[2] = ui->checkBoxSerialPassThru3->isChecked(); - serial_passthrough_enabled[3] = ui->checkBoxSerialPassThru4->isChecked(); } void @@ -152,6 +160,24 @@ SettingsPorts::on_pushButtonSerialPassThru4_clicked() DeviceConfig::ConfigureDevice(&serial_passthrough_device, 4, qobject_cast(Settings::settings)); } +void +SettingsPorts::on_pushButtonSerialPassThru5_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 5, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru6_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 6, qobject_cast(Settings::settings)); +} + +void +SettingsPorts::on_pushButtonSerialPassThru7_clicked() +{ + DeviceConfig::ConfigureDevice(&serial_passthrough_device, 7, qobject_cast(Settings::settings)); +} + void SettingsPorts::on_checkBoxSerialPassThru1_clicked(bool checked) { @@ -175,3 +201,23 @@ SettingsPorts::on_checkBoxSerialPassThru4_clicked(bool checked) { ui->pushButtonSerialPassThru4->setEnabled(checked); } + +#if 0 +void +SettingsPorts::on_checkBoxSerialPassThru5_clicked(bool checked) +{ + ui->pushButtonSerialPassThru5->setEnabled(checked); +} + +void +SettingsPorts::on_checkBoxSerialPassThru6_clicked(bool checked) +{ + ui->pushButtonSerialPassThru6->setEnabled(checked); +} + +void +SettingsPorts::on_checkBoxSerialPassThru7_clicked(bool checked) +{ + ui->pushButtonSerialPassThru7->setEnabled(checked); +} +#endif \ No newline at end of file diff --git a/src/qt/qt_settingsports.hpp b/src/qt/qt_settingsports.hpp index a5129d35f2..1ecb051afa 100644 --- a/src/qt/qt_settingsports.hpp +++ b/src/qt/qt_settingsports.hpp @@ -15,6 +15,18 @@ class SettingsPorts : public QWidget { ~SettingsPorts(); void save(); + +#if 0 +private slots: + void on_checkBoxSerialPassThru7_clicked(bool checked); + +private slots: + void on_checkBoxSerialPassThru6_clicked(bool checked); + +private slots: + void on_checkBoxSerialPassThru5_clicked(bool checked); +#endif + private slots: void on_checkBoxSerialPassThru4_clicked(bool checked); @@ -24,6 +36,18 @@ private slots: private slots: void on_checkBoxSerialPassThru2_clicked(bool checked); +private slots: + void on_checkBoxSerialPassThru1_clicked(bool checked); + +private slots: + void on_pushButtonSerialPassThru7_clicked(); + +private slots: + void on_pushButtonSerialPassThru6_clicked(); + +private slots: + void on_pushButtonSerialPassThru5_clicked(); + private slots: void on_pushButtonSerialPassThru4_clicked(); @@ -37,15 +61,11 @@ private slots: void on_pushButtonSerialPassThru1_clicked(); private slots: - void on_checkBoxSerialPassThru1_clicked(bool checked); - -private slots: + void on_checkBoxParallel4_stateChanged(int arg1); void on_checkBoxParallel3_stateChanged(int arg1); void on_checkBoxParallel2_stateChanged(int arg1); void on_checkBoxParallel1_stateChanged(int arg1); - void on_checkBoxParallel4_stateChanged(int arg1); - private: Ui::SettingsPorts *ui; }; diff --git a/src/qt/qt_settingsstoragecontrollers.cpp b/src/qt/qt_settingsstoragecontrollers.cpp index 389e22852c..a86362909e 100644 --- a/src/qt/qt_settingsstoragecontrollers.cpp +++ b/src/qt/qt_settingsstoragecontrollers.cpp @@ -56,8 +56,8 @@ SettingsStorageControllers::save() auto *cbox = findChild(QString("comboBoxSCSI%1").arg(i + 1)); scsi_card_current[i] = cbox->currentData().toInt(); } - hdc_current = ui->comboBoxHD->currentData().toInt(); - fdc_type = ui->comboBoxFD->currentData().toInt(); + hdc_current[0] = ui->comboBoxHD->currentData().toInt(); + fdc_current[0] = ui->comboBoxFD->currentData().toInt(); cdrom_interface_current = ui->comboBoxCDInterface->currentData().toInt(); ide_ter_enabled = ui->checkBoxTertiaryIDE->isChecked() ? 1 : 0; ide_qua_enabled = ui->checkBoxQuaternaryIDE->isChecked() ? 1 : 0; @@ -92,7 +92,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) if (device_is_valid(hdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); - if (c == hdc_current) { + if (c == hdc_current[0]) { selectedRow = row - removeRows; } } @@ -110,6 +110,14 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) c = 0; selectedRow = 0; while (true) { +#if 0 + /* Skip "internal" if machine doesn't have it. */ + if ((c == 1) && (machine_has_flags(machineId, MACHINE_FDC) == 0)) { + c++; + continue; + } +#endif + QString name = DeviceConfig::DeviceName(fdc_card_getdevice(c), fdc_card_get_internal_name(c), 1); if (name.isEmpty()) { break; @@ -120,7 +128,7 @@ SettingsStorageControllers::onCurrentMachineChanged(int machineId) if (device_is_valid(fdc_dev, machineId)) { int row = Models::AddEntry(model, name, c); - if (c == fdc_type) { + if (c == fdc_current[0]) { selectedRow = row - removeRows; } } diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index fc111e5b4f..b24731f555 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -256,6 +256,9 @@ ui_sb_update_icon_state(int tag, int state) case SB_TEXT: break; } + + if (main_window != nullptr) + main_window->updateStatusEmptyIcons(); } void diff --git a/src/qt/qt_util.cpp b/src/qt/qt_util.cpp index 0a59cdf5d4..5c90592729 100644 --- a/src/qt/qt_util.cpp +++ b/src/qt/qt_util.cpp @@ -14,6 +14,8 @@ * * Copyright 2022 Teemu Korhonen */ +#include +#include #include #include #include @@ -70,7 +72,11 @@ DlgFilter(std::initializer_list extensions, bool last) QString currentUuid() { - return QUuid::createUuidV5(QUuid{}, QString(usr_path)).toString(QUuid::WithoutBraces); + auto configPath = QFileInfo(cfg_path).dir().canonicalPath(); + if(!configPath.endsWith("/")) { + configPath.append("/"); + } + return QUuid::createUuidV5(QUuid{}, configPath).toString(QUuid::WithoutBraces); } bool compareUuid() @@ -82,6 +88,11 @@ bool compareUuid() storeCurrentUuid(); return true; } + // Do not prompt on mismatch if the system does not have any configured NICs. Just update the uuid + if(!hasConfiguredNICs() && uuid != currentUuid()) { + storeCurrentUuid(); + return true; + } // The uuid appears to be a valid, at least by length. // Compare with a simple string match return uuid == currentUuid(); @@ -99,14 +110,24 @@ generateNewMacAdresses() for (int i = 0; i < NET_CARD_MAX; ++i) { auto net_card = net_cards_conf[i]; if (net_card.device_num != 0) { - const auto network_device = network_card_getdevice(net_card.device_num); + const auto network_device = network_card_getdevice(net_card.device_num); device_context_t device_context; - - device_set_context(&device_context, network_device, i+1); + device_set_context(&device_context, network_device, i + 1); auto generatedMac = QString::asprintf("%02X:%02X:%02X", random_generate(), random_generate(), random_generate()).toLower(); config_set_string(device_context.name, "mac", generatedMac.toUtf8().constData()); } } } +bool +hasConfiguredNICs() +{ + for (int i = 0; i < NET_CARD_MAX; ++i) { + if (const auto net_card = net_cards_conf[i]; net_card.device_num != 0) { + return true; + } + } + return false; +} + } diff --git a/src/qt/qt_util.hpp b/src/qt/qt_util.hpp index 07e44b621d..6a0bdc30b1 100644 --- a/src/qt/qt_util.hpp +++ b/src/qt/qt_util.hpp @@ -17,6 +17,7 @@ QString currentUuid(); void storeCurrentUuid(); bool compareUuid(); void generateNewMacAdresses(); +bool hasConfiguredNICs(); }; #endif diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 3ca091ae64..66d8ad8e5d 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -176,9 +176,6 @@ WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) RAWKEYBOARD rawKB = raw->data.keyboard; scancode = rawKB.MakeCode; - if (kbd_req_capture && !mouse_capture) - return; - /* If it's not a scan code that starts with 0xE1 */ if ((rawKB.Flags & RI_KEY_E1)) { if (rawKB.MakeCode == 0x1D) { @@ -199,9 +196,10 @@ WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) scancode = convert_scan_code(scancode); /* Remap it according to the list from the Registry */ - if (scancode != scancode_map[scancode]) - pclog("Scan code remap: %03X -> %03X\n", scancode, scancode); - scancode = scancode_map[scancode]; + if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { + pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); + scancode = scancode_map[scancode]; + } /* If it's not 0xFFFF, send it to the emulated keyboard. diff --git a/src/qt/win_thread.c b/src/qt/win_thread.c new file mode 100644 index 0000000000..9a4f046b36 --- /dev/null +++ b/src/qt/win_thread.c @@ -0,0 +1,179 @@ +/* + * 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. + * + * Implement threads and mutexes for the Win32 platform. + * + * + * + * Authors: Sarah Walker, + * Fred N. van Kempen, + * + * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2018 Fred N. van Kempen. + */ +#define UNICODE +#define BITMAP WINDOWS_BITMAP +#include +#include +#include +#undef BITMAP +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/plat.h> +#include <86box/thread.h> + +typedef struct { + HANDLE handle; +} win_event_t; + +/* For compatibility with thread.h, but Win32 does not allow named threads. */ +thread_t * +thread_create_named(void (*func)(void *param), void *param, UNUSED(const char *name)) +{ + uintptr_t bt = _beginthread(func, 0, param); + return ((thread_t *) bt); +} + +int +thread_test_mutex(thread_t *arg) +{ + if (arg == NULL) + return (0); + + return (WaitForSingleObject(arg, 0) == WAIT_OBJECT_0) ? 1 : 0; +} + +int +thread_wait(thread_t *arg) +{ + if (arg == NULL) + return (0); + + if (WaitForSingleObject(arg, INFINITE)) + return (1); + + return (0); +} + +event_t * +thread_create_event(void) +{ + win_event_t *ev = malloc(sizeof(win_event_t)); + + ev->handle = CreateEvent(NULL, FALSE, FALSE, NULL); + + return ((event_t *) ev); +} + +void +thread_set_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return; + + SetEvent(ev->handle); +} + +void +thread_reset_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return; + + ResetEvent(ev->handle); +} + +int +thread_wait_event(event_t *arg, int timeout) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return (0); + + if (ev->handle == NULL) + return (0); + + if (timeout == -1) + timeout = INFINITE; + + if (WaitForSingleObject(ev->handle, timeout)) + return (1); + + return (0); +} + +void +thread_destroy_event(event_t *arg) +{ + win_event_t *ev = (win_event_t *) arg; + + if (arg == NULL) + return; + + CloseHandle(ev->handle); + + free(ev); +} + +mutex_t * +thread_create_mutex(void) +{ + mutex_t *mutex = malloc(sizeof(CRITICAL_SECTION)); + + InitializeCriticalSection(mutex); + + return mutex; +} + +int +thread_wait_mutex(mutex_t *mutex) +{ + if (mutex == NULL) + return (0); + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; + + EnterCriticalSection(critsec); + + return 1; +} + +int +thread_release_mutex(mutex_t *mutex) +{ + if (mutex == NULL) + return (0); + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; + + LeaveCriticalSection(critsec); + + return 1; +} + +void +thread_close_mutex(mutex_t *mutex) +{ + if (mutex == NULL) + return; + + LPCRITICAL_SECTION critsec = (LPCRITICAL_SECTION) mutex; + + DeleteCriticalSection(critsec); + + free(critsec); +} diff --git a/src/qt_resources.qrc b/src/qt_resources.qrc index 265fb63760..1f63417867 100644 --- a/src/qt_resources.qrc +++ b/src/qt_resources.qrc @@ -11,6 +11,11 @@ qt/icons/cdrom_disabled.ico qt/icons/cdrom_empty.ico qt/icons/cdrom_empty_active.ico + qt/icons/cdrom_mute.ico + qt/icons/cdrom_unmute.ico + qt/icons/cdrom_image.ico + qt/icons/cdrom_folder.ico + qt/icons/cdrom_host.ico qt/icons/display.ico qt/icons/floppy_35.ico qt/icons/floppy_35_active.ico @@ -58,6 +63,9 @@ qt/icons/send_cae.ico qt/icons/settings.ico + + qt/icons/warning.ico + qt/texture_vert.spv qt/texture_frag.spv diff --git a/src/scsi/CMakeLists.txt b/src/scsi/CMakeLists.txt index 01e20b9299..c710f758d5 100644 --- a/src/scsi/CMakeLists.txt +++ b/src/scsi/CMakeLists.txt @@ -9,10 +9,24 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(scsi OBJECT scsi.c scsi_device.c scsi_cdrom.c scsi_disk.c - scsi_x54x.c scsi_aha154x.c scsi_buslogic.c scsi_ncr5380.c scsi_ncr53c400.c - scsi_t128.c scsi_ncr53c8xx.c scsi_pcscsi.c scsi_spock.c) +add_library(scsi OBJECT + scsi.c + scsi_device.c + scsi_cdrom.c + scsi_disk.c + scsi_x54x.c + scsi_aha154x.c + scsi_buslogic.c + scsi_ncr5380.c + scsi_ncr53c400.c + scsi_t128.c + scsi_ncr53c8xx.c + scsi_pcscsi.c + scsi_spock.c +) diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 23c3e65f3e..bbce63651a 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -47,27 +47,13 @@ double scsi_bus_speed[SCSI_BUS_MAX] = { 0.0, 0.0, 0.0, 0.0 }; static uint8_t next_scsi_bus = 0; -static const device_t scsi_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - typedef const struct { const device_t *device; } SCSI_CARD; static SCSI_CARD scsi_cards[] = { // clang-format off - { &scsi_none_device, }, + { &device_none, }, { &aha154xa_device, }, { &aha154xb_device, }, { &aha154xc_device, }, @@ -96,6 +82,7 @@ static SCSI_CARD scsi_cards[] = { { &ncr53c825a_pci_device, }, { &ncr53c860_pci_device, }, { &ncr53c875_pci_device, }, + { &am53c974_pci_device, }, { &dc390_pci_device, }, { &buslogic_445s_device, }, { &buslogic_445c_device, }, diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 2927d797c0..7d9f1ba240 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -921,7 +921,7 @@ aha_setnvr(x54x_t *dev) FILE *fp; /* Only if this device has an EEPROM. */ - if (dev->nvr_path == NULL) + if (dev->nvr_path[0] == 0x00) return; /* Allocate and initialize the EEPROM. */ @@ -1043,7 +1043,7 @@ aha_init(const device_t *info) case AHA_154xC: strcpy(dev->name, "AHA-154xC"); dev->bios_path = "roms/scsi/adaptec/aha1542c102.bin"; - dev->nvr_path = "aha1542c.nvr"; + sprintf(dev->nvr_path, "aha1542c_%i.nvr", device_get_instance()); dev->fw_rev = "D001"; dev->rom_shram = 0x3F80; /* shadow RAM address base */ dev->rom_shramsz = 128; /* size of shadow RAM */ @@ -1059,7 +1059,7 @@ aha_init(const device_t *info) case AHA_154xCF: strcpy(dev->name, "AHA-154xCF"); dev->bios_path = "roms/scsi/adaptec/aha1542cf211.bin"; - dev->nvr_path = "aha1542cf.nvr"; + sprintf(dev->nvr_path, "aha1542cf_%i.nvr", device_get_instance()); dev->fw_rev = "E001"; dev->rom_shram = 0x3F80; /* shadow RAM address base */ dev->rom_shramsz = 128; /* size of shadow RAM */ @@ -1080,7 +1080,7 @@ aha_init(const device_t *info) bios_rev = (char *) device_get_config_bios("bios_rev"); dev->bios_path = (char *) device_get_bios_file(info, bios_rev, 0); dev->mcode_path = (char *) device_get_bios_file(info, bios_rev, 1); - dev->nvr_path = "aha1542cp.nvr"; + sprintf(dev->nvr_path, "aha1542cp_%i.nvr", device_get_instance()); dev->fw_rev = aha1542cp_rev; dev->rom_shram = 0x3F80; /* shadow RAM address base */ dev->rom_shramsz = 128; /* size of shadow RAM */ diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index 262d9600c4..d014945a71 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -279,7 +279,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = { { 0, 0 }, { 0, 0 }, { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} + { GPMODE_CAPABILITIES_PAGE, 0x12, 7, 0, 0x3f, 1, 0x0d, 3, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} }; static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { @@ -325,7 +325,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { { 0, 0 }, { 0, 0 }, { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} + { GPMODE_CAPABILITIES_PAGE, 0x12, 7, 0, 0x3f, 1, 0x0d, 3, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} }; static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_sony_scsi = { @@ -371,7 +371,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_sony_scsi = { 0, 0 }, { 0, 0 }, { 0, 0 }, - { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} + { GPMODE_CAPABILITIES_PAGE, 0x12, 7, 0, 0x3f, 1, 0x0d, 3, 2, 0xC2, 1, 0, 0, 0, 2, 0xC2, 0, 0, 0, 0 }} }; static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { @@ -1080,7 +1080,6 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) static void scsi_cdrom_command_complete(scsi_cdrom_t *dev) { - ui_sb_update_icon(SB_CDROM | dev->id, 0); dev->packet_status = PHASE_COMPLETE; scsi_cdrom_command_common(dev); dev->tf->phase = 3; @@ -1183,8 +1182,6 @@ scsi_cdrom_cmd_error(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; dev->tf->pos = 0; @@ -1200,8 +1197,6 @@ scsi_cdrom_unit_attention(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; - if (dev->unit_attention) - dev->tf->error |= MCR_ERR; dev->tf->status = READY_STAT | ERR_STAT; dev->tf->phase = 3; dev->tf->pos = 0; @@ -1544,13 +1539,51 @@ scsi_cdrom_insert(void *priv) { scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; - if (!dev) + if ((dev == NULL) || (dev->drv == NULL)) return; - dev->unit_attention = 1; - /* Turn off the medium changed status. */ - dev->drv->cd_status &= ~CD_STATUS_MEDIUM_CHANGED; - scsi_cdrom_log("CD-ROM %i: Media insert\n", dev->id); + if (dev->drv->ops == NULL) { + dev->unit_attention = 0; + dev->drv->cd_status = CD_STATUS_EMPTY; + scsi_cdrom_log("CD-ROM %i: Media removal\n", dev->id); + } else if (dev->drv->cd_status & CD_STATUS_TRANSITION) { + dev->unit_attention = 1; + /* Turn off the medium changed status. */ + dev->drv->cd_status &= ~(CD_STATUS_TRANSITION | CD_STATUS_MEDIUM_CHANGED); + scsi_cdrom_log("CD-ROM %i: Media insert\n", dev->id); + } else { + dev->unit_attention = 0; + dev->drv->cd_status |= CD_STATUS_TRANSITION; + scsi_cdrom_log("CD-ROM %i: Media transition\n", dev->id); + } +} + +static int +scsi_command_check_ready(scsi_cdrom_t *dev, uint8_t *cdb) +{ + int ret = 0; + + if (scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) { + /*Note by TC1995: Some vendor commands from X vendor don't really check for ready status + but they do on Y vendor. Quite confusing I know.*/ + if (scsi_cdrom_command_flags[cdb[0]] & SCSI_ONLY) switch (dev->drv->type) { + default: + ret = 1; + break; + case CDROM_TYPE_DEC_RRD45_0436: + case CDROM_TYPE_SONY_CDU541_10i: + case CDROM_TYPE_SONY_CDU561_18k: + case CDROM_TYPE_SONY_CDU76S_100: + case CDROM_TYPE_TEXEL_DMXX24_100: + if (cdb[0] == 0xC0) + break; + ret = 1; + break; + } else + ret = 1; + } + + return ret; } static int @@ -1594,16 +1627,26 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) goto skip_ready_check; } - if ((dev->drv->cd_status & CD_STATUS_MEDIUM_CHANGED) || (ext_medium_changed == 1)) - scsi_cdrom_insert((void *) dev); + if (dev->drv->cd_status & CD_STATUS_TRANSITION) { + if ((cdb[0] == GPCMD_TEST_UNIT_READY) || (cdb[0] == GPCMD_REQUEST_SENSE)) + ready = 0; + else { + scsi_cdrom_insert((void *) dev); - ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1); + ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1); + } + } else { + if ((dev->drv->cd_status & CD_STATUS_MEDIUM_CHANGED) || (ext_medium_changed == 1)) + scsi_cdrom_insert((void *) dev); + + ready = (dev->drv->cd_status != CD_STATUS_EMPTY) || (ext_medium_changed == -1); + } skip_ready_check: /* If the drive is not ready, there is no reason to keep the UNIT ATTENTION condition present, as we only use it to mark disc changes. */ - if (!ready && dev->unit_attention) + if (!ready && (dev->unit_attention > 0)) dev->unit_attention = 0; /* If the UNIT ATTENTION condition is set and the command does not allow @@ -1631,19 +1674,18 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) scsi_cdrom_sense_clear(dev, cdb[0]); /* Next it's time for NOT READY. */ - if (!ready) - dev->media_status = MEC_MEDIA_REMOVAL; + if (ready) + dev->media_status = dev->unit_attention ? MEC_NEW_MEDIA : MEC_NO_CHANGE; else - dev->media_status = (dev->unit_attention) ? MEC_NEW_MEDIA : MEC_NO_CHANGE; + dev->media_status = MEC_MEDIA_REMOVAL; - if ((scsi_cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) { + if (!ready && scsi_command_check_ready(dev, cdb)) { scsi_cdrom_log("CD-ROM %i: Not ready (%02X)\n", dev->id, cdb[0]); scsi_cdrom_not_ready(dev); return 0; } scsi_cdrom_log("CD-ROM %i: Continuing with command %02X\n", dev->id, cdb[0]); - return 1; } @@ -1692,7 +1734,7 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt buffer[2] = SENSE_ILLEGAL_REQUEST; buffer[12] = ASC_AUDIO_PLAY_OPERATION; buffer[13] = (dev->drv->cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } else if (dev->unit_attention && (scsi_cdrom_sense_key == 0)) { + } else if (dev->unit_attention && ((scsi_cdrom_sense_key == 0) || (scsi_cdrom_sense_key == 2))) { buffer[2] = SENSE_UNIT_ATTENTION; buffer[12] = ASC_MEDIUM_MAY_HAVE_CHANGED; buffer[13] = 0; @@ -1706,8 +1748,8 @@ scsi_cdrom_request_sense(scsi_cdrom_t *dev, uint8_t *buffer, uint8_t alloc_lengt dev->unit_attention = 0; } - /* Clear the sense stuff as per the spec. */ - scsi_cdrom_sense_clear(dev, GPCMD_REQUEST_SENSE); + if (dev->drv->cd_status & CD_STATUS_TRANSITION) + scsi_cdrom_insert((void *) dev); } void @@ -1801,7 +1843,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) memcpy(dev->current_cdb, cdb, 12); dev->sony_vendor = 0; - if (cdb[0] != 0) { + // if (cdb[0] != 0) { scsi_cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, dev->unit_attention); @@ -1810,7 +1852,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); - } + // } msf = cdb[1] & 2; dev->sector_len = 0; @@ -1822,6 +1864,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) return; begin: + if (cdb[0] != GPCMD_REQUEST_SENSE) { + /* Clear the sense stuff as per the spec. */ + scsi_cdrom_sense_clear(dev, cdb[0]); + } switch (cdb[0]) { case GPCMD_TEST_UNIT_READY: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -2318,7 +2364,9 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) max_len = (cdb[7] << 8) | cdb[8]; /* only feature 0 is supported */ - if ((cdb[2] != 0) || (cdb[3] > 2)) { + if ((feature > 3) && (feature != 0x010) && + (feature != 0x1d) && (feature != 0x01e) && + (feature != 0x01f) && (feature != 0x103)) { scsi_cdrom_invalid_field(dev); scsi_cdrom_buf_free(dev); return; @@ -2393,6 +2441,73 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) alloc_length += 8; b += 8; } + if ((feature == 3) || ((cdb[1] & 3) < 2)) { + b[1] = 2; + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 4; + + b[4] = 0x0d; + /* The early CD-ROM drives we emulate (NEC CDR-260 for ATAPI and + early vendor SCSI CD-ROM models) are caddy drives, the later + ones are tray drives. */ + if (dev->drv->bus_type == CDROM_BUS_SCSI) + b[4] |= ((dev->drv->type == CDROM_TYPE_86BOX_100) ? 0x20 : 0x00); + else + b[4] |= ((dev->drv->type == CDROM_TYPE_NEC_260_100) || + ((dev->drv->type == CDROM_TYPE_NEC_260_101)) ? 0x00 : 0x20); + + alloc_length += 8; + b += 8; + } + if ((feature == 0x10) || ((cdb[1] & 3) < 2)) { + b[1] = 0x10; + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 8; + + b[6] = 8; + b[9] = 0x10; + + alloc_length += 12; + b += 12; + } + if ((feature == 0x1d) || ((cdb[1] & 3) < 2)) { + b[1] = 0x1d; + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 0; + + alloc_length += 4; + b += 4; + } + if ((feature == 0x1e) || ((cdb[1] & 3) < 2)) { + b[1] = 0x1e; + b[2] = (2 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 4; + + b[4] = 0; + + alloc_length += 8; + b += 8; + } + if ((feature == 0x1f) || ((cdb[1] & 3) < 2)) { + b[1] = 0x1f; + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 0; + + alloc_length += 4; + b += 4; + } + if ((feature == 0x103) || ((cdb[1] & 3) < 2)) { + b[0] = 1; + b[1] = 3; + b[2] = (0 << 2) | 0x02 | 0x01; /* persistent and current */ + b[3] = 0; + + b[4] = 7; + b[6] = 1; + + alloc_length += 8; + b += 8; + } dev->buffer[0] = ((alloc_length - 4) >> 24) & 0xff; dev->buffer[1] = ((alloc_length - 4) >> 16) & 0xff; @@ -3000,6 +3115,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { if (cdb[1] == 0) { + format = cdb[7]; ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, dev->buffer); dev->buffer[0] = (ret >> 8); dev->buffer[1] = (ret & 0xff); @@ -3211,9 +3327,6 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (dev->drv->bus_type == CDROM_BUS_SCSI) { dev->buffer[3] = 0x02; switch (dev->drv->type) { - case CDROM_TYPE_86BOX_100: - dev->buffer[2] = 0x05; /*SCSI-2 compliant*/ - break; case CDROM_TYPE_CHINON_CDS431_H42: case CDROM_TYPE_DEC_RRD45_0436: case CDROM_TYPE_MATSHITA_501_10b: @@ -3222,7 +3335,6 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) case CDROM_TYPE_TEAC_CD50_100: case CDROM_TYPE_TEAC_R55S_10R: case CDROM_TYPE_TEXEL_DMXX24_100: - case CDROM_TYPE_TOSHIBA_XM3201B_3232: dev->buffer[2] = 0x00; dev->buffer[3] = 0x01; /*SCSI-1 compliant*/ break; @@ -3234,6 +3346,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) case CDROM_TYPE_NEC_464_105: dev->buffer[3] = 0x00; /*SCSI unknown version per NEC manuals*/ break; + case CDROM_TYPE_TOSHIBA_XM3201B_3232: + dev->buffer[2] = 0x01; + dev->buffer[3] = 0x01; /*SCSI-1 compliant*/ + break; default: dev->buffer[2] = 0x02; /*SCSI-2 compliant*/ break; diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index f29e854310..792dad31b4 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -461,7 +461,7 @@ scsi_disk_command_common(scsi_disk_t *dev) (uint64_t) period); dev->callback += period; break; - default: + default: dev->callback = 0; break; } @@ -511,7 +511,6 @@ scsi_disk_command_common(scsi_disk_t *dev) static void scsi_disk_command_complete(scsi_disk_t *dev) { - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); dev->packet_status = PHASE_COMPLETE; scsi_disk_command_common(dev); } @@ -1647,7 +1646,7 @@ scsi_disk_identify(ide_t *ide, int ide_has_dma) scsi_disk_log("ATAPI Identify: %s\n", device_identify); /* ATAPI device, direct-access device, non-removable media, accelerated DRQ */ - ide->buffer[0] = 0x8000 | (0 << 8) | 0x00 | (2 << 5); + ide->buffer[0] = 0x8000 | (0 << 8) | 0x00 | (2 << 5); ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ diff --git a/src/scsi/scsi_ncr53c400.c b/src/scsi/scsi_ncr53c400.c index ca4d28ffb9..0e772c16c0 100644 --- a/src/scsi/scsi_ncr53c400.c +++ b/src/scsi/scsi_ncr53c400.c @@ -146,8 +146,8 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr400->busy = 1; - if (!(ncr->mode & MODE_MONITOR_BUSY)) - timer_on_auto(&ncr400->timer, ncr->period / 280.0); + if (!(ncr->mode & MODE_MONITOR_BUSY) && ((scsi_device_get_callback(dev) > 0.0))) + timer_on_auto(&ncr400->timer, ncr->period / 250.0); } } break; @@ -182,9 +182,12 @@ ncr53c400_write(uint32_t addr, uint8_t val, void *priv) memset(ncr400->buffer, 0, MIN(128, dev->buffer_length)); if (ncr->mode & MODE_MONITOR_BUSY) timer_on_auto(&ncr400->timer, ncr->period); - else + else if (scsi_device_get_callback(dev) > 0.0) timer_on_auto(&ncr400->timer, 40.0); - ncr53c400_log("DMA timer on, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); + else + timer_on_auto(&ncr400->timer, ncr->period); + + ncr53c400_log("DMA timer on=%02x, callback=%lf, scsi buflen=%d, waitdata=%d, waitcomplete=%d, clearreq=%d, datawait=%d, enabled=%d.\n", ncr->mode & MODE_MONITOR_BUSY, scsi_device_get_callback(dev), dev->buffer_length, ncr->wait_complete, ncr->wait_data, ncr->wait_complete, ncr->clear_req, ncr->data_wait, timer_is_enabled(&ncr400->timer)); } break; @@ -239,8 +242,8 @@ ncr53c400_read(uint32_t addr, void *priv) if (ncr400->buffer_host_pos == MIN(128, dev->buffer_length)) { ncr400->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr53c400_log("Transfer busy read, status = %02x.\n", ncr400->status_ctrl); - if (!(ncr->mode & MODE_MONITOR_BUSY)) - timer_on_auto(&ncr400->timer, ncr->period / 280.0); + if (!(ncr->mode & MODE_MONITOR_BUSY) && (scsi_device_get_callback(dev) > 0.0)) + timer_on_auto(&ncr400->timer, ncr->period / 250.0); } } break; diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index f640c49a6d..1395c2f6f4 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -205,7 +205,7 @@ typedef enum { } scsi_state_t; typedef struct ncr53c8xx_t { - char *nvr_path; + char nvr_path[64]; uint8_t pci_slot; uint8_t chip, wide; int has_bios; @@ -2571,33 +2571,33 @@ ncr53c8xx_init(const device_t *info) switch (dev->chip) { case CHIP_810: - dev->nvr_path = "ncr53c810.nvr"; + sprintf(dev->nvr_path, "ncr53c810_%i.nvr", device_get_instance()); dev->wide = 0; break; case CHIP_815: dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c815.nvr"; + sprintf(dev->nvr_path, "ncr53c815_%i.nvr", device_get_instance()); dev->wide = 0; break; case CHIP_820: - dev->nvr_path = "ncr53c820.nvr"; + sprintf(dev->nvr_path, "ncr53c820_%i.nvr", device_get_instance()); dev->wide = 1; break; case CHIP_825: dev->chip_rev = 0x26; - dev->nvr_path = "ncr53c825a.nvr"; + sprintf(dev->nvr_path, "ncr53c825a_%i.nvr", device_get_instance()); dev->wide = 1; break; case CHIP_860: scsi_bus_set_speed(dev->bus, 20000000.0); dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c860.nvr"; + sprintf(dev->nvr_path, "ncr53c860_%i.nvr", device_get_instance()); dev->wide = 1; break; case CHIP_875: scsi_bus_set_speed(dev->bus, 40000000.0); dev->chip_rev = 0x04; - dev->nvr_path = "ncr53c875.nvr"; + sprintf(dev->nvr_path, "ncr53c875_%i.nvr", device_get_instance()); dev->wide = 1; break; } diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 674bbdabfa..be50d9a891 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -26,6 +26,7 @@ #include #include #include +#include #define HAVE_STDARG_H #include #include <86box/86box.h> @@ -47,6 +48,7 @@ #include <86box/fifo8.h> #define DC390_ROM "roms/scsi/esp_pci/INT13.BIN" +#define AM53C974_ROM "roms/scsi/esp_pci/harom.bin" #define ESP_REGS 16 #define ESP_FIFO_SZ 16 @@ -152,7 +154,7 @@ typedef struct esp_t { mem_mapping_t mmio_mapping; mem_mapping_t ram_mapping; - char *nvr_path; + char nvr_path[64]; uint8_t pci_slot; int has_bios; int BIOSBase; @@ -174,6 +176,7 @@ typedef struct esp_t { Fifo8 cmdfifo; uint32_t do_cmd; uint8_t cmdfifo_cdb_offset; + int data_ready; int32_t xfer_counter; int dma_enabled; @@ -186,6 +189,7 @@ typedef struct esp_t { pc_timer_t timer; + int local; int mca; uint16_t Base; uint8_t HostID; @@ -204,6 +208,9 @@ typedef struct esp_t { #define READ_FROM_DEVICE 1 #define WRITE_TO_DEVICE 0 +uint8_t esp_pci_regs[256]; +bar_t esp_pci_bar[2]; + #ifdef ENABLE_ESP_LOG int esp_do_log = ENABLE_ESP_LOG; @@ -223,16 +230,62 @@ esp_log(const char *fmt, ...) #endif static void esp_dma_enable(esp_t *dev, int level); -static void esp_do_dma(esp_t *dev, scsi_device_t *sd); -static void esp_do_nodma(esp_t *dev, scsi_device_t *sd); +static void esp_do_dma(esp_t *dev); +static void esp_do_nodma(esp_t *dev); static void esp_pci_dma_memory_rw(esp_t *dev, uint8_t *buf, uint32_t len, int dir); static void esp_timer_on(esp_t *dev, scsi_device_t *sd, double p); static void esp_command_complete(void *priv, uint32_t status); -static void esp_pci_command_complete(void *priv, uint32_t status); +static void esp_dma_ti_check(esp_t *dev); +static void esp_nodma_ti_dataout(esp_t *dev); static void esp_pci_soft_reset(esp_t *dev); static void esp_pci_hard_reset(esp_t *dev); static void handle_ti(void *priv); +static int +esp_cdb_length(uint8_t *buf) +{ + int cdb_len; + + switch (buf[0] >> 5) { + case 0: + case 3: + cdb_len = 6; + break; + case 1: + case 2: + case 6: + cdb_len = 10; + break; + case 4: + cdb_len = 16; + break; + case 5: + cdb_len = 12; + break; + default: + cdb_len = -1; + break; + } + return cdb_len; +} + +static void +esp_pci_update_irq(esp_t *dev) +{ + int scsi_level = !!(dev->dma_regs[DMA_STAT] & DMA_STAT_SCSIINT); + int dma_level = (dev->dma_regs[DMA_CMD] & DMA_CMD_INTE_D) ? + !!(dev->dma_regs[DMA_STAT] & DMA_STAT_DONE) : 0; + int level = scsi_level || dma_level; + + if (level) { + pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + esp_log("Raising PCI IRQ...\n"); + } else { + pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); + esp_log("Lowering PCI IRQ...\n"); + } +} + static void esp_irq(esp_t *dev, int level) { @@ -246,12 +299,21 @@ esp_irq(esp_t *dev, int level) } } else { if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); - esp_log("Raising IRQ...\n"); - } else { - pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state); - esp_log("Lowering IRQ...\n"); - } + dev->dma_regs[DMA_STAT] |= DMA_STAT_SCSIINT; + /* + * If raising the ESP IRQ to indicate end of DMA transfer, set + * DMA_STAT_DONE at the same time. In theory this should be done in + * esp_pci_dma_memory_rw(), however there is a delay between setting + * DMA_STAT_DONE and the ESP IRQ arriving which is visible to the + * guest that can cause confusion e.g. Linux + */ + if ((dev->dma_regs[DMA_CMD] & DMA_CMD_MASK) == 0x3 && + dev->dma_regs[DMA_WBC] == 0) + dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; + } else + dev->dma_regs[DMA_STAT] &= ~DMA_STAT_SCSIINT; + + esp_pci_update_irq(dev); } } @@ -274,41 +336,46 @@ esp_lower_irq(esp_t *dev) } static void -esp_fifo_push(Fifo8 *fifo, uint8_t val) +esp_set_phase(esp_t *dev, uint8_t phase) { - if (fifo8_num_used(fifo) == fifo->capacity) { + dev->rregs[ESP_RSTAT] &= ~7; + dev->rregs[ESP_RSTAT] |= phase; +} + +static uint8_t +esp_get_phase(esp_t *dev) +{ + return dev->rregs[ESP_RSTAT] & 7; +} + +static void +esp_fifo_push(esp_t *dev, uint8_t val) +{ + if (fifo8_num_used(&dev->fifo) == dev->fifo.capacity) return; - } - fifo8_push(fifo, val); + fifo8_push(&dev->fifo, val); } static uint8_t -esp_fifo_pop(Fifo8 *fifo) +esp_fifo_pop(esp_t *dev) { - if (fifo8_is_empty(fifo)) { - return 0; - } + uint8_t val; - return fifo8_pop(fifo); + if (fifo8_is_empty(&dev->fifo)) + val = 0; + else + val = fifo8_pop(&dev->fifo); + + return val; } static uint32_t -esp_fifo_pop_buf(Fifo8 *fifo, uint8_t *dest, int maxlen) +esp_fifo_pop_buf(esp_t *dev, uint8_t *dest, int maxlen) { - const uint8_t *buf; - uint32_t n; + uint32_t len = fifo8_pop_buf(&dev->fifo, dest, maxlen); - if (maxlen == 0) { - return 0; - } - - buf = fifo8_pop_buf(fifo, maxlen, &n); - if (dest) { - memcpy(dest, buf, n); - } - - return n; + return len; } static uint32_t @@ -326,9 +393,14 @@ esp_get_tc(esp_t *dev) static void esp_set_tc(esp_t *dev, uint32_t dmalen) { + uint32_t old_tc = esp_get_tc(dev); + dev->rregs[ESP_TCLO] = dmalen; dev->rregs[ESP_TCMID] = dmalen >> 8; dev->rregs[ESP_TCHI] = dmalen >> 16; + + if (old_tc && !dmalen) + dev->rregs[ESP_RSTAT] |= STAT_TC; } static uint32_t @@ -343,64 +415,91 @@ esp_get_stc(esp_t *dev) return dmalen; } -static void -esp_dma_done(esp_t *dev) -{ - dev->rregs[ESP_RSTAT] |= STAT_TC; - dev->rregs[ESP_RINTR] = INTR_BS; - dev->rregs[ESP_RSEQ] = 0; - dev->rregs[ESP_RFLAGS] = 0; - esp_set_tc(dev, 0); - esp_log("ESP DMA Finished\n"); - esp_raise_irq(dev); +static int +esp_select(esp_t *dev) +{ + scsi_device_t *sd; + + dev->id = dev->wregs[ESP_WBUSID] & BUSID_DID; + sd = &scsi_devices[dev->bus][dev->id]; + + dev->ti_size = 0; + dev->rregs[ESP_RSEQ] = SEQ_0; + + if (!scsi_device_present(sd)) { + esp_log("ESP SCSI no devices on ID %d, LUN %d\n", dev->id, dev->lun); + /* No such drive */ + dev->rregs[ESP_RSTAT] = 0; + dev->rregs[ESP_RINTR] = INTR_DC; + esp_raise_irq(dev); + return -1; + } else + esp_log("ESP SCSI device present on ID %d, LUN %d\n", dev->id, dev->lun); + + return 0; } -static uint32_t -esp_get_cmd(esp_t *dev, uint32_t maxlen) + /* Callback to indicate that the SCSI layer has completed a transfer. */ +static void +esp_transfer_data(esp_t *dev) { - uint8_t buf[ESP_CMDFIFO_SZ]; - uint32_t dmalen; - uint32_t n; + if (!dev->data_ready) { + dev->data_ready = 1; - dev->id = dev->wregs[ESP_WBUSID] & BUSID_DID; - if (dev->dma) { - dmalen = MIN(esp_get_tc(dev), maxlen); - esp_log("ESP Get data, dmalen = %d\n", dmalen); - if (dmalen == 0) - return 0; - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < dmalen) { - int val = dma_channel_read(dev->DmaChannel); - buf[dev->dma_86c01.pos++] = val & 0xff; - } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else { - esp_pci_dma_memory_rw(dev, buf, dmalen, WRITE_TO_DEVICE); - } - dmalen = MIN(fifo8_num_free(&dev->cmdfifo), dmalen); - fifo8_push_all(&dev->cmdfifo, buf, dmalen); - } else { - dmalen = MIN(fifo8_num_used(&dev->fifo), maxlen); - esp_log("ESP Get command, dmalen = %i\n", dmalen); - if (dmalen == 0) { - return 0; + switch (dev->rregs[ESP_CMD]) { + case CMD_SEL: + case (CMD_SEL | CMD_DMA): + case CMD_SELATN: + case (CMD_SELATN | CMD_DMA): + /* + * Initial incoming data xfer is complete for sequencer command + * so raise deferred bus service and function complete interrupt + */ + dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); + dev->rregs[ESP_RSEQ] = SEQ_CD; + break; + + case CMD_SELATNS: + case (CMD_SELATNS | CMD_DMA): + /* + * Initial incoming data xfer is complete so raise command + * completion interrupt + */ + dev->rregs[ESP_RINTR] |= INTR_BS; + dev->rregs[ESP_RSEQ] = SEQ_MO; + break; + + case CMD_TI: + case (CMD_TI | CMD_DMA): + /* + * Bus service interrupt raised because of initial change to + * DATA phase + */ + dev->rregs[ESP_CMD] = 0; + dev->rregs[ESP_RINTR] |= INTR_BS; + break; } - n = esp_fifo_pop_buf(&dev->fifo, buf, dmalen); - n = MIN(fifo8_num_free(&dev->cmdfifo), n); - fifo8_push_all(&dev->cmdfifo, buf, n); - } - dev->ti_size = 0; - fifo8_reset(&dev->fifo); + esp_raise_irq(dev); + } - dev->rregs[ESP_RINTR] |= INTR_FC; - dev->rregs[ESP_RSEQ] = SEQ_CD; + /* + * Always perform the initial transfer upon reception of the next TI + * command to ensure the DMA/non-DMA status of the command is correct. + * It is not possible to use s->dma directly in the section below as + * some OSs send non-DMA NOP commands after a DMA transfer. Hence if the + * async data transfer is delayed then s->dma is set incorrectly. + */ - return dmalen; + if (dev->rregs[ESP_CMD] == (CMD_TI | CMD_DMA)) { + /* When the SCSI layer returns more data, raise deferred INTR_BS */ + esp_dma_ti_check(dev); + esp_do_dma(dev); + } else if (dev->rregs[ESP_CMD] == CMD_TI) + esp_do_nodma(dev); } + static void esp_do_command_phase(esp_t *dev) { @@ -416,7 +515,7 @@ esp_do_command_phase(esp_t *dev) if (!cmdlen) return; - esp_fifo_pop_buf(&dev->cmdfifo, buf, cmdlen); + fifo8_pop_buf(&dev->cmdfifo, buf, cmdlen); for (int i = 0; i < cmdlen; i++) esp_log("CDB[%i] = %02x\n", i, buf[i]); @@ -427,46 +526,32 @@ esp_do_command_phase(esp_t *dev) dev->ti_size = sd->buffer_length; dev->xfer_counter = sd->buffer_length; - esp_log("ESP SCSI Command = 0x%02x, ID = %d, LUN = %d, len = %d\n", buf[0], dev->id, dev->lun, sd->buffer_length); + esp_log("ESP SCSI Command = 0x%02x, ID = %d, LUN = %d, len = %d, phase = %02x.\n", buf[0], dev->id, dev->lun, sd->buffer_length, sd->phase); fifo8_reset(&dev->cmdfifo); + dev->data_ready = 0; if (sd->buffer_length > 0) { - /* This should be set to the underlying device's buffer by command phase 0. */ - dev->rregs[ESP_RSTAT] = STAT_TC; - dev->rregs[ESP_RSEQ] = SEQ_CD; - if (sd->phase == SCSI_PHASE_DATA_IN) { - dev->rregs[ESP_RSTAT] |= STAT_DI; + esp_set_phase(dev, STAT_DI); esp_log("ESP Data In\n"); esp_timer_on(dev, sd, scsi_device_get_callback(sd)); } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - dev->rregs[ESP_RSTAT] |= STAT_DO; - esp_log("ESP Data Out\n"); + esp_set_phase(dev, STAT_DO); dev->ti_size = -sd->buffer_length; + esp_log("ESP Data Out\n"); esp_timer_on(dev, sd, scsi_device_get_callback(sd)); } esp_log("ESP SCSI Start reading/writing\n"); - esp_do_dma(dev, sd); + esp_do_dma(dev); } else { esp_log("ESP SCSI Command with no length\n"); - if (dev->mca) { - if (buf[0] == 0x43) { - dev->rregs[ESP_RSTAT] = STAT_DI | STAT_TC; - dev->rregs[ESP_RSEQ] = SEQ_CD; - esp_do_dma(dev, sd); - } else - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); + esp_command_complete(dev, sd->status); } - - scsi_device_identify(sd, SCSI_LUN_USE_CDB); - - dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); - esp_raise_irq(dev); + esp_transfer_data(dev); } + static void esp_do_message_phase(esp_t *dev) { @@ -474,7 +559,8 @@ esp_do_message_phase(esp_t *dev) uint8_t message; if (dev->cmdfifo_cdb_offset) { - message = esp_fifo_pop(&dev->cmdfifo); + message = fifo8_is_empty(&dev->cmdfifo) ? 0 : + fifo8_pop(&dev->cmdfifo); dev->lun = message & 7; dev->cmdfifo_cdb_offset--; @@ -497,7 +583,7 @@ esp_do_message_phase(esp_t *dev) if (dev->cmdfifo_cdb_offset) { len = MIN(dev->cmdfifo_cdb_offset, fifo8_num_used(&dev->cmdfifo)); - esp_fifo_pop_buf(&dev->cmdfifo, NULL, len); + fifo8_drop(&dev->cmdfifo, len); dev->cmdfifo_cdb_offset = 0; } } @@ -505,9 +591,10 @@ esp_do_message_phase(esp_t *dev) static void esp_do_cmd(esp_t *dev) { + esp_log("DO CMD.\n"); esp_do_message_phase(dev); - if (dev->cmdfifo_cdb_offset == 0) - esp_do_command_phase(dev); + assert(dev->cmdfifo_cdb_offset == 0); + esp_do_command_phase(dev); } static void @@ -544,265 +631,550 @@ esp_hard_reset(esp_t *dev) esp_log("ESP Reset\n"); for (uint8_t i = 0; i < 16; i++) scsi_device_reset(&scsi_devices[dev->bus][i]); + timer_stop(&dev->timer); } +static int +esp_cdb_ready(esp_t *dev) +{ + int len = fifo8_num_used(&dev->cmdfifo) - dev->cmdfifo_cdb_offset; + const uint8_t *pbuf; + uint32_t n; + int cdblen; + + if (len <= 0) + return 0; + + pbuf = fifo8_peek_bufptr(&dev->cmdfifo, len, &n); + if (n < len) { + /* + * In normal use the cmdfifo should never wrap, but include this check + * to prevent a malicious guest from reading past the end of the + * cmdfifo data buffer below + */ + return 0; + } + + cdblen = esp_cdb_length((uint8_t *)&pbuf[dev->cmdfifo_cdb_offset]); + + return (cdblen < 0) ? 0 : (len >= cdblen); +} + +static void +esp_dma_ti_check(esp_t *dev) +{ + if ((esp_get_tc(dev) == 0) && (fifo8_num_used(&dev->fifo) < 2)) { + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } +} + static void -esp_do_nodma(esp_t *dev, scsi_device_t *sd) +esp_do_dma(esp_t *dev) { - int count; + scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; + uint8_t buf[ESP_CMDFIFO_SZ]; + uint32_t len; + + esp_log("ESP SCSI Actual DMA len = %d\n", esp_get_tc(dev)); + + len = esp_get_tc(dev); + + switch (esp_get_phase(dev)) { + case STAT_MO: + len = MIN(len, fifo8_num_free(&dev->cmdfifo)); + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + int val = dma_channel_read(dev->DmaChannel); + buf[dev->dma_86c01.pos++] = val & 0xff; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE); + + esp_set_tc(dev, esp_get_tc(dev) - len); + fifo8_push_all(&dev->cmdfifo, buf, len); + dev->cmdfifo_cdb_offset += len; + + switch (dev->rregs[ESP_CMD]) { + case (CMD_SELATN | CMD_DMA): + if (fifo8_num_used(&dev->cmdfifo) >= 1) { + /* First byte received, switch to command phase */ + esp_set_phase(dev, STAT_CD); + dev->rregs[ESP_RSEQ] = SEQ_CD; + dev->cmdfifo_cdb_offset = 1; + + if (fifo8_num_used(&dev->cmdfifo) > 1) { + /* Process any additional command phase data */ + esp_do_dma(dev); + } + } + break; + + case (CMD_SELATNS | CMD_DMA): + if (fifo8_num_used(&dev->cmdfifo) == 1) { + /* First byte received, stop in message out phase */ + dev->rregs[ESP_RSEQ] = SEQ_MO; + dev->cmdfifo_cdb_offset = 1; + + /* Raise command completion interrupt */ + dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); + esp_raise_irq(dev); + } + break; + + case (CMD_TI | CMD_DMA): + /* ATN remains asserted until TC == 0 */ + if (esp_get_tc(dev) == 0) { + esp_set_phase(dev, STAT_CD); + dev->rregs[ESP_CMD] = 0; + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } + break; - esp_log("ESP SCSI Actual FIFO len = %d\n", dev->xfer_counter); + default: + break; + } + break; - if (dev->do_cmd) { - esp_log("ESP Command on FIFO\n"); - dev->ti_size = 0; + case STAT_CD: + len = MIN(len, fifo8_num_free(&dev->cmdfifo)); + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + int val = dma_channel_read(dev->DmaChannel); + buf[dev->dma_86c01.pos++] = val & 0xff; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, len, WRITE_TO_DEVICE); + + fifo8_push_all(&dev->cmdfifo, buf, len); + esp_set_tc(dev, esp_get_tc(dev) - len); + dev->ti_size = 0; + if (esp_get_tc(dev) == 0) { + /* Command has been received */ + esp_do_cmd(dev); + } + break; - if ((dev->rregs[ESP_RSTAT] & 7) == STAT_CD) { - if (dev->cmdfifo_cdb_offset == fifo8_num_used(&dev->cmdfifo)) { - esp_log("CDB offset = %i used return\n", dev->cmdfifo_cdb_offset); + case STAT_DO: + if (!dev->xfer_counter && esp_get_tc(dev)) { + /* Defer until data is available. */ return; } + if (len > dev->xfer_counter) + len = dev->xfer_counter; - dev->do_cmd = 0; - esp_do_cmd(dev); - } else { - dev->cmdfifo_cdb_offset = fifo8_num_used(&dev->cmdfifo); - esp_log("CDB offset = %i used\n", dev->cmdfifo_cdb_offset); + switch (dev->rregs[ESP_CMD]) { + case (CMD_TI | CMD_DMA): + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + int val = dma_channel_read(dev->DmaChannel); + esp_log("ESP SCSI DMA write for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff); + sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff; + dev->dma_86c01.pos++; + } + dma_set_drq(dev->DmaChannel, 0); + dev->dma_86c01.pos = 0; + } else + esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, WRITE_TO_DEVICE); - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); - } - return; - } + esp_set_tc(dev, esp_get_tc(dev) - len); - if (dev->xfer_counter == 0) { - /* Wait until data is available. */ - esp_log("(ID=%02i LUN=%02i): FIFO no data available\n", dev->id, dev->lun); - return; - } + dev->buffer_pos += len; + dev->xfer_counter -= len; + dev->ti_size += len; + break; - esp_log("ESP FIFO = %d, buffer length = %d\n", dev->xfer_counter, sd->buffer_length); + case (CMD_PAD | CMD_DMA): + /* Copy TC zero bytes into the incoming stream */ + memset(sd->sc->temp_buffer + dev->buffer_pos, 0, len); - if (sd->phase == SCSI_PHASE_DATA_IN) { - if (fifo8_is_empty(&dev->fifo)) { - fifo8_push(&dev->fifo, sd->sc->temp_buffer[dev->buffer_pos]); - dev->buffer_pos++; - dev->ti_size--; - dev->xfer_counter--; - } - } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - count = MIN(fifo8_num_used(&dev->fifo), ESP_FIFO_SZ); - esp_fifo_pop_buf(&dev->fifo, sd->sc->temp_buffer + dev->buffer_pos, count); - dev->buffer_pos += count; - dev->ti_size += count; - dev->xfer_counter -= count; - } + dev->buffer_pos += len; + dev->xfer_counter -= len; + dev->ti_size += len; + break; - esp_log("ESP FIFO Transfer bytes = %d\n", dev->xfer_counter); - if (dev->xfer_counter <= 0) { - if (sd->phase == SCSI_PHASE_DATA_OUT) { - if (dev->ti_size < 0) { - esp_log("ESP FIFO Keep writing\n"); - esp_do_nodma(dev, sd); - } else { - esp_log("ESP FIFO Write finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { + default: + break; + } + + if ((dev->xfer_counter <= 0) && (fifo8_num_used(&dev->fifo) < 2)) { + /* Defer until the scsi layer has completed */ + if (dev->ti_size < 0) { + esp_log("ESP SCSI Keep writing\n"); + esp_do_dma(dev); + } else { + esp_log("ESP SCSI Write finished\n"); + scsi_device_command_phase1(sd); esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); + } + return; + } + + esp_dma_ti_check(dev); + break; + + case STAT_DI: + if (!dev->xfer_counter && esp_get_tc(dev)) { + /* Defer until data is available. */ + return; } - } else if (sd->phase == SCSI_PHASE_DATA_IN) { - /* If there is still data to be read from the device then - complete the DMA operation immediately. Otherwise defer - until the scsi layer has completed. */ - if (dev->ti_size <= 0) { - esp_log("ESP FIFO Read finished\n"); + if (len > dev->xfer_counter) + len = dev->xfer_counter; + + switch (dev->rregs[ESP_CMD]) { + case (CMD_TI | CMD_DMA): + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); + esp_log("ESP SCSI DMA read for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); + dev->dma_86c01.pos++; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, len, READ_FROM_DEVICE); + + dev->buffer_pos += len; + dev->xfer_counter -= len; + dev->ti_size -= len; + esp_set_tc(dev, esp_get_tc(dev) - len); + break; + + case (CMD_PAD | CMD_DMA): + dev->buffer_pos += len; + dev->xfer_counter -= len; + dev->ti_size -= len; + esp_set_tc(dev, esp_get_tc(dev) - len); + break; + + default: + break; + } + + if ((dev->xfer_counter <= 0) && !dev->ti_size && esp_get_tc(dev)) { + /* If the guest underflows TC then terminate SCSI request */ + esp_log("ESP SCSI Read finished (underflow).\n"); scsi_device_command_phase1(sd); - if (dev->mca) { + esp_command_complete(dev, sd->status); + return; + } + + if ((dev->xfer_counter <= 0) && (fifo8_num_used(&dev->fifo) < 2)) { + /* Defer until the scsi layer has completed */ + if (dev->ti_size <= 0) { + esp_log("ESP SCSI Read finished\n"); + scsi_device_command_phase1(sd); esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); - } else { - esp_log("ESP FIFO Keep reading\n"); - esp_do_nodma(dev, sd); + } else { + esp_log("ESP SCSI Keep reading\n"); + esp_do_dma(dev); + } + return; } - } - } else { - /* Partially filled a scsi buffer. Complete immediately. */ - esp_log("ESP SCSI Partially filled the FIFO buffer\n"); - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); + esp_dma_ti_check(dev); + break; + + case STAT_ST: + switch (dev->rregs[ESP_CMD]) { + case (CMD_ICCS | CMD_DMA): + len = MIN(len, 1); + + if (len) { + buf[0] = dev->status; + + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + dma_channel_write(dev->DmaChannel, buf[dev->dma_86c01.pos]); + dev->dma_86c01.pos++; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, len, READ_FROM_DEVICE); + + esp_set_tc(dev, esp_get_tc(dev) - len); + esp_set_phase(dev, STAT_MI); + + if (esp_get_tc(dev) > 0) { + /* Process any message in phase data */ + esp_do_dma(dev); + } + } + break; + + default: + /* Consume remaining data if the guest underflows TC */ + if (fifo8_num_used(&dev->fifo) < 2) { + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } + break; + } + break; + + case STAT_MI: + switch (dev->rregs[ESP_CMD]) { + case (CMD_ICCS | CMD_DMA): + len = MIN(len, 1); + + if (len) { + buf[0] = 0; + + if (dev->mca) { + dma_set_drq(dev->DmaChannel, 1); + while (dev->dma_86c01.pos < len) { + dma_channel_write(dev->DmaChannel, buf[dev->dma_86c01.pos]); + dev->dma_86c01.pos++; + } + dev->dma_86c01.pos = 0; + dma_set_drq(dev->DmaChannel, 0); + } else + esp_pci_dma_memory_rw(dev, buf, len, READ_FROM_DEVICE); + + esp_set_tc(dev, esp_get_tc(dev) - len); + + /* Raise end of command interrupt */ + dev->rregs[ESP_RINTR] |= INTR_FC; + esp_raise_irq(dev); + } + break; + } + break; + + default: + break; } } static void -esp_do_dma(esp_t *dev, scsi_device_t *sd) +esp_nodma_ti_dataout(esp_t *dev) { - uint8_t buf[ESP_CMDFIFO_SZ]; - uint32_t tdbc; - int count; - - esp_log("ESP SCSI Actual DMA len = %d\n", esp_get_tc(dev)); + scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; + int len; - if (!scsi_device_present(sd)) { - esp_log("ESP SCSI no devices on ID %d, LUN %d\n", dev->id, dev->lun); - /* No such drive */ - dev->rregs[ESP_RSTAT] = 0; - dev->rregs[ESP_RINTR] = INTR_DC; - dev->rregs[ESP_RSEQ] = SEQ_0; - esp_raise_irq(dev); - fifo8_reset(&dev->cmdfifo); + if (!dev->xfer_counter) { + /* Defer until data is available. */ return; - } else { - esp_log("ESP SCSI device found on ID %d, LUN %d\n", dev->id, dev->lun); } + len = MIN(dev->xfer_counter, ESP_FIFO_SZ); + len = MIN(len, fifo8_num_used(&dev->fifo)); + esp_fifo_pop_buf(dev, sd->sc->temp_buffer + dev->buffer_pos, len); + dev->buffer_pos += len; + dev->xfer_counter -= len; + dev->ti_size += len; - count = tdbc = esp_get_tc(dev); - - if (dev->mca) { - if (sd->buffer_length < 0) { - if (dev->dma_enabled) - goto done; - else - goto partial; + if (dev->xfer_counter <= 0) { + if (dev->ti_size < 0) { + esp_log("ESP SCSI Keep writing\n"); + esp_nodma_ti_dataout(dev); + } else { + esp_log("ESP SCSI Write finished\n"); + scsi_device_command_phase1(sd); + esp_command_complete(dev, sd->status); } + return; } - if (dev->do_cmd) { - esp_log("ESP Command on DMA\n"); - count = MIN(count, fifo8_num_free(&dev->cmdfifo)); - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < count) { - dma_channel_write(dev->DmaChannel, buf[dev->dma_86c01.pos]); - dev->dma_86c01.pos++; + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); +} + +static void +esp_do_nodma(esp_t *dev) +{ + scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; + uint8_t buf[ESP_FIFO_SZ]; + int len; + + switch (esp_get_phase(dev)) { + case STAT_MO: + switch (dev->rregs[ESP_CMD]) { + case CMD_SELATN: + /* Copy FIFO into cmdfifo */ + len = esp_fifo_pop_buf(dev, buf, fifo8_num_used(&dev->fifo)); + len = MIN(fifo8_num_free(&dev->cmdfifo), len); + fifo8_push_all(&dev->cmdfifo, buf, len); + + if (fifo8_num_used(&dev->cmdfifo) >= 1) { + /* First byte received, switch to command phase */ + esp_set_phase(dev, STAT_CD); + dev->rregs[ESP_RSEQ] = SEQ_CD; + dev->cmdfifo_cdb_offset = 1; + + if (fifo8_num_used(&dev->cmdfifo) > 1) { + /* Process any additional command phase data */ + esp_do_nodma(dev); + } + } + break; + + case CMD_SELATNS: + /* Copy one byte from FIFO into cmdfifo */ + len = esp_fifo_pop_buf(dev, buf, + MIN(fifo8_num_used(&dev->fifo), 1)); + len = MIN(fifo8_num_free(&dev->cmdfifo), len); + fifo8_push_all(&dev->cmdfifo, buf, len); + + if (fifo8_num_used(&dev->cmdfifo) >= 1) { + /* First byte received, stop in message out phase */ + dev->rregs[ESP_RSEQ] = SEQ_MO; + dev->cmdfifo_cdb_offset = 1; + + /* Raise command completion interrupt */ + dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); + esp_raise_irq(dev); + } + break; + + case CMD_TI: + /* Copy FIFO into cmdfifo */ + len = esp_fifo_pop_buf(dev, buf, fifo8_num_used(&dev->fifo)); + len = MIN(fifo8_num_free(&dev->cmdfifo), len); + fifo8_push_all(&dev->cmdfifo, buf, len); + + /* ATN remains asserted until FIFO empty */ + dev->cmdfifo_cdb_offset = fifo8_num_used(&dev->cmdfifo); + esp_set_phase(dev, STAT_CD); + dev->rregs[ESP_CMD] = 0; + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + break; + + default: + break; } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else - esp_pci_dma_memory_rw(dev, buf, count, READ_FROM_DEVICE); - fifo8_push_all(&dev->cmdfifo, buf, count); - dev->ti_size = 0; + break; - if ((dev->rregs[ESP_RSTAT] & 7) == STAT_CD) { - if (dev->cmdfifo_cdb_offset == fifo8_num_used(&dev->cmdfifo)) - return; + case STAT_CD: + switch (dev->rregs[ESP_CMD]) { + case CMD_TI: + /* Copy FIFO into cmdfifo */ + len = esp_fifo_pop_buf(dev, buf, fifo8_num_used(&dev->fifo)); + len = MIN(fifo8_num_free(&dev->cmdfifo), len); + fifo8_push_all(&dev->cmdfifo, buf, len); + + /* CDB may be transferred in one or more TI commands */ + if (esp_cdb_ready(dev)) { + /* Command has been received */ + esp_do_cmd(dev); + } else { + /* + * If data was transferred from the FIFO then raise bus + * service interrupt to indicate transfer complete. Otherwise + * defer until the next FIFO write. + */ + if (len) { + /* Raise interrupt to indicate transfer complete */ + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + } + } + break; - dev->do_cmd = 0; - esp_do_cmd(dev); - } else { - dev->cmdfifo_cdb_offset = fifo8_num_used(&dev->cmdfifo); + case (CMD_SEL | CMD_DMA): + case (CMD_SELATN | CMD_DMA): + /* Copy FIFO into cmdfifo */ + len = esp_fifo_pop_buf(dev, buf, fifo8_num_used(&dev->fifo)); + len = MIN(fifo8_num_free(&dev->cmdfifo), len); + fifo8_push_all(&dev->cmdfifo, buf, len); + + /* Handle when DMA transfer is terminated by non-DMA FIFO write */ + if (esp_cdb_ready(dev)) { + /* Command has been received */ + esp_do_cmd(dev); + } + break; - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_CD; - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); - } - return; - } + case CMD_SEL: + case CMD_SELATN: + /* FIFO already contain entire CDB: copy to cmdfifo and execute */ + len = esp_fifo_pop_buf(dev, buf, fifo8_num_used(&dev->fifo)); + len = MIN(fifo8_num_free(&dev->cmdfifo), len); + fifo8_push_all(&dev->cmdfifo, buf, len); - if (dev->xfer_counter == 0) { - /* Wait until data is available. */ - esp_log("(ID=%02i LUN=%02i): DMA no data available\n", dev->id, dev->lun); - return; - } + esp_do_cmd(dev); + break; - esp_log("ESP SCSI dmaleft = %d, buffer length = %d\n", esp_get_tc(dev), sd->buffer_length); + default: + break; + } + break; - /* Make sure count is never bigger than buffer_length. */ - if (count > dev->xfer_counter) - count = dev->xfer_counter; + case STAT_DO: + /* Accumulate data in FIFO until non-DMA TI is executed */ + break; - if (sd->phase == SCSI_PHASE_DATA_IN) { - esp_log("ESP SCSI Read, dma cnt = %i, ti size = %i, positive len = %i\n", esp_get_tc(dev), dev->ti_size, count); - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < count) { - dma_channel_write(dev->DmaChannel, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); - esp_log("ESP SCSI DMA read for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos]); - dev->dma_86c01.pos++; + case STAT_DI: + if (!dev->xfer_counter) { + /* Defer until data is available. */ + return; } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else { - esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, count, READ_FROM_DEVICE); - } - } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - esp_log("ESP SCSI Write, negative len = %i, ti size = %i, dma cnt = %i\n", count, -dev->ti_size, esp_get_tc(dev)); - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < count) { - int val = dma_channel_read(dev->DmaChannel); - esp_log("ESP SCSI DMA write for 53C9x: pos = %i, val = %02x\n", dev->dma_86c01.pos, val & 0xff); - sd->sc->temp_buffer[dev->buffer_pos + dev->dma_86c01.pos] = val & 0xff; - dev->dma_86c01.pos++; + if (fifo8_is_empty(&dev->fifo)) { + esp_fifo_push(dev, sd->sc->temp_buffer[dev->buffer_pos]); + dev->buffer_pos++; + dev->ti_size--; + dev->xfer_counter--; } - dma_set_drq(dev->DmaChannel, 0); - dev->dma_86c01.pos = 0; - } else - esp_pci_dma_memory_rw(dev, sd->sc->temp_buffer + dev->buffer_pos, count, WRITE_TO_DEVICE); - } - esp_set_tc(dev, esp_get_tc(dev) - count); - dev->buffer_pos += count; - dev->xfer_counter -= count; - if (sd->phase == SCSI_PHASE_DATA_IN) { - dev->ti_size -= count; - } else if (sd->phase == SCSI_PHASE_DATA_OUT) { - dev->ti_size += count; - } - esp_log("ESP SCSI Transfer bytes = %d\n", dev->xfer_counter); - if (dev->xfer_counter <= 0) { - if (sd->phase == SCSI_PHASE_DATA_OUT) { - if (dev->ti_size < 0) { - esp_log("ESP SCSI Keep writing\n"); - esp_do_dma(dev, sd); - } else { - esp_log("ESP SCSI Write finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { + if (dev->xfer_counter <= 0) { + if (dev->ti_size <= 0) { + esp_log("ESP FIFO Read finished\n"); + scsi_device_command_phase1(sd); esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); + } else { + esp_log("ESP FIFO Keep reading\n"); + esp_do_nodma(dev); + } + return; } - } else if (sd->phase == SCSI_PHASE_DATA_IN) { - /* If there is still data to be read from the device then - complete the DMA operation immediately. Otherwise defer - until the scsi layer has completed. */ - if (dev->ti_size <= 0) { -done: - esp_log("ESP SCSI Read finished\n"); - scsi_device_command_phase1(sd); - if (dev->mca) { - esp_command_complete(dev, sd->status); - } else - esp_pci_command_complete(dev, sd->status); - } else { - esp_log("ESP SCSI Keep reading\n"); - esp_do_dma(dev, sd); + + /* If preloading the FIFO, defer until TI command issued */ + if (dev->rregs[ESP_CMD] != CMD_TI) + return; + + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); + break; + + case STAT_ST: + switch (dev->rregs[ESP_CMD]) { + case CMD_ICCS: + esp_fifo_push(dev, dev->status); + esp_set_phase(dev, STAT_MI); + + /* Process any message in phase data */ + esp_do_nodma(dev); + break; + default: + break; } - } - } else { - /* Partially filled a scsi buffer. Complete immediately. */ -partial: - esp_log("ESP SCSI Partially filled the SCSI buffer\n"); - esp_dma_done(dev); - } -} + break; -static void -esp_report_command_complete(esp_t *dev, uint32_t status) -{ - esp_log("ESP Command complete\n"); + case STAT_MI: + switch (dev->rregs[ESP_CMD]) { + case CMD_ICCS: + esp_fifo_push(dev, 0); - dev->ti_size = 0; - dev->status = status; - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; - esp_dma_done(dev); + /* Raise end of command interrupt */ + dev->rregs[ESP_RINTR] |= INTR_FC; + esp_raise_irq(dev); + break; + default: + break; + } + break; + } } /* Callback to indicate that the SCSI layer has completed a command. */ @@ -810,18 +1182,36 @@ static void esp_command_complete(void *priv, uint32_t status) { esp_t *dev = (esp_t *) priv; + scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; - esp_report_command_complete(dev, status); -} - -static void -esp_pci_command_complete(void *priv, uint32_t status) -{ - esp_t *dev = (esp_t *) priv; + dev->ti_size = 0; + dev->status = status; + + switch (dev->rregs[ESP_CMD]) { + case CMD_SEL: + case (CMD_SEL | CMD_DMA): + case CMD_SELATN: + case (CMD_SELATN | CMD_DMA): + /* + * Switch to status phase. For non-DMA transfers from the target the last + * byte is still in the FIFO + */ + dev->rregs[ESP_RINTR] |= (INTR_BS | INTR_FC); + dev->rregs[ESP_RSEQ] = SEQ_CD; + break; + case CMD_TI: + case (CMD_TI | CMD_DMA): + dev->rregs[ESP_CMD] = 0; + break; + default: + break; + } + /* Raise bus service interrupt to indicate change to STATUS phase */ + scsi_device_identify(sd, SCSI_LUN_USE_CDB); - esp_command_complete(dev, status); - dev->dma_regs[DMA_WBC] = 0; - dev->dma_regs[DMA_STAT] |= DMA_STAT_DONE; + esp_set_phase(dev, STAT_ST); + dev->rregs[ESP_RINTR] |= INTR_BS; + esp_raise_irq(dev); } static void @@ -838,18 +1228,31 @@ esp_timer_on(esp_t *dev, scsi_device_t *sd, double p) timer_on_auto(&dev->timer, dev->period + 40.0); } +static void +handle_pad(esp_t *dev) +{ + if (dev->dma) { + esp_log("ESP Handle PAD, do data, minlen = %i\n", esp_get_tc(dev)); + esp_do_dma(dev); + } else { + esp_log("ESP Handle PAD, do nodma, minlen = %i\n", dev->xfer_counter); + esp_do_nodma(dev); + } +} + static void handle_ti(void *priv) { esp_t *dev = (esp_t *) priv; - scsi_device_t *sd = &scsi_devices[dev->bus][dev->id]; if (dev->dma) { esp_log("ESP Handle TI, do data, minlen = %i\n", esp_get_tc(dev)); - esp_do_dma(dev, sd); + esp_do_dma(dev); } else { esp_log("ESP Handle TI, do nodma, minlen = %i\n", dev->xfer_counter); - esp_do_nodma(dev, sd); + esp_do_nodma(dev); + if (esp_get_phase(dev) == STAT_DO) + esp_nodma_ti_dataout(dev); } } @@ -857,95 +1260,59 @@ static void handle_s_without_atn(void *priv) { esp_t *dev = (esp_t *) priv; - int len; - len = esp_get_cmd(dev, ESP_CMDFIFO_SZ); - esp_log("ESP SEL w/o ATN len = %d, id = %d\n", len, dev->id); - if (len > 0) { - dev->cmdfifo_cdb_offset = 0; - dev->do_cmd = 0; - esp_do_cmd(dev); - } else if (len == 0) { - dev->do_cmd = 1; - /* Target present, but no cmd yet - switch to command phase */ - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RSTAT] = STAT_CD; - } + if (esp_select(dev) < 0) + return; + + esp_set_phase(dev, STAT_CD); + dev->cmdfifo_cdb_offset = 0; + + if (dev->dma) + esp_do_dma(dev); + else + esp_do_nodma(dev); } static void handle_satn(void *priv) { esp_t *dev = (esp_t *) priv; - int len; - - len = esp_get_cmd(dev, ESP_CMDFIFO_SZ); - esp_log("ESP SEL with ATN len = %d, id = %d\n", len, dev->id); - if (len > 0) { - dev->cmdfifo_cdb_offset = 1; - dev->do_cmd = 0; - esp_do_cmd(dev); - } else if (len == 0) { - dev->do_cmd = 1; - /* Target present, but no cmd yet - switch to command phase */ - dev->rregs[ESP_RSEQ] = SEQ_CD; - dev->rregs[ESP_RSTAT] = STAT_CD; - } + + if (esp_select(dev) < 0) + return; + + esp_set_phase(dev, STAT_MO); + + if (dev->dma) + esp_do_dma(dev); + else + esp_do_nodma(dev); } static void handle_satn_stop(void *priv) { esp_t *dev = (esp_t *) priv; - int cmdlen; - - cmdlen = esp_get_cmd(dev, 1); - if (cmdlen > 0) { - dev->do_cmd = 1; - dev->cmdfifo_cdb_offset = 1; - dev->rregs[ESP_RSTAT] = STAT_MO; - dev->rregs[ESP_RINTR] = INTR_BS | INTR_FC; - dev->rregs[ESP_RSEQ] = SEQ_MO; - esp_log("ESP SCSI Command len = %d, raising IRQ\n", cmdlen); - esp_raise_irq(dev); - } else if (cmdlen == 0) { - dev->do_cmd = 1; - /* Target present, switch to message out phase */ - dev->rregs[ESP_RSEQ] = SEQ_MO; - dev->rregs[ESP_RSTAT] = STAT_MO; - } + + if (esp_select(dev) < 0) + return; + + esp_set_phase(dev, STAT_MO); + dev->cmdfifo_cdb_offset = 0; + + if (dev->dma) + esp_do_dma(dev); + else + esp_do_nodma(dev); } static void esp_write_response(esp_t *dev) { - uint8_t buf[2]; - - buf[0] = dev->status; - buf[1] = 0; - esp_log("esp_write_response(): %02X %02X\n", buf[0], buf[1]); - - if (dev->dma) { - if (dev->mca) { - dma_set_drq(dev->DmaChannel, 1); - while (dev->dma_86c01.pos < 2) { - int val = dma_channel_read(dev->DmaChannel); - buf[dev->dma_86c01.pos++] = val & 0xff; - } - dev->dma_86c01.pos = 0; - dma_set_drq(dev->DmaChannel, 0); - } else - esp_pci_dma_memory_rw(dev, buf, 2, WRITE_TO_DEVICE); - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; - dev->rregs[ESP_RINTR] = INTR_BS | INTR_FC; - dev->rregs[ESP_RSEQ] = SEQ_CD; - } else { - fifo8_reset(&dev->fifo); - fifo8_push_all(&dev->fifo, buf, 2); - dev->rregs[ESP_RFLAGS] = 2; - } - esp_log("ESP SCSI ICCS IRQ\n"); - esp_raise_irq(dev); + if (dev->dma) + esp_do_dma(dev); + else + esp_do_nodma(dev); } static void @@ -953,13 +1320,13 @@ esp_callback(void *priv) { esp_t *dev = (esp_t *) priv; - if (dev->dma_enabled || dev->do_cmd || ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_PAD)) { + if (dev->dma_enabled || !dev->dma || ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_PAD)) { if ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_TI) { esp_log("ESP SCSI Handle TI Callback\n"); handle_ti(dev); } else if ((dev->rregs[ESP_CMD] & CMD_CMD) == CMD_PAD) { esp_log("ESP SCSI Handle PAD Callback\n"); - handle_ti(dev); + handle_pad(dev); } } @@ -973,20 +1340,7 @@ esp_reg_read(esp_t *dev, uint32_t saddr) switch (saddr) { case ESP_FIFO: - if ((dev->rregs[ESP_RSTAT] & 7) == STAT_DI) { - if (dev->ti_size) { - esp_log("TI size FIFO = %i\n", dev->ti_size); - esp_do_nodma(dev, &scsi_devices[dev->bus][dev->id]); - } else { - /* - * The last byte of a non-DMA transfer has been read out - * of the FIFO so switch to status phase - */ - dev->rregs[ESP_RSTAT] = STAT_TC | STAT_ST; - } - } - - dev->rregs[ESP_FIFO] = esp_fifo_pop(&dev->fifo); + dev->rregs[ESP_FIFO] = esp_fifo_pop(dev); ret = dev->rregs[ESP_FIFO]; break; case ESP_RINTR: @@ -1033,21 +1387,10 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) dev->rregs[ESP_RSTAT] &= ~STAT_TC; break; case ESP_FIFO: - if (dev->do_cmd) { - esp_fifo_push(&dev->cmdfifo, val); - esp_log("ESP CmdVal = %02x\n", val); - /* - * If any unexpected message out/command phase data is - * transferred using non-DMA, raise the interrupt - */ - if (dev->rregs[ESP_CMD] == CMD_TI) { - dev->rregs[ESP_RINTR] |= INTR_BS; - esp_raise_irq(dev); - } - } else { - esp_fifo_push(&dev->fifo, val); - esp_log("ESP fifoval = %02x\n", val); - } + if (!fifo8_is_full(&dev->fifo)) + esp_fifo_push(dev, val); + + esp_do_nodma(dev); break; case ESP_CMD: dev->rregs[saddr] = val; @@ -1056,6 +1399,8 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) dev->dma = 1; /* Reload DMA counter. */ esp_set_tc(dev, esp_get_stc(dev)); + if (!esp_get_stc(dev)) + esp_set_tc(dev, 0x10000); } else { dev->dma = 0; esp_log("ESP Command not for DMA\n"); @@ -1091,6 +1436,11 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) case CMD_TI: esp_log("Transfer Information val = %02X\n", val); break; + case CMD_ICCS: + esp_write_response(dev); + dev->rregs[ESP_RINTR] |= INTR_FC; + dev->rregs[ESP_RSTAT] |= STAT_MI; + break; case CMD_SEL: handle_s_without_atn(dev); break; @@ -1100,11 +1450,6 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) case CMD_SELATNS: handle_satn_stop(dev); break; - case CMD_ICCS: - esp_write_response(dev); - dev->rregs[ESP_RINTR] |= INTR_FC; - dev->rregs[ESP_RSTAT] |= STAT_MI; - break; case CMD_MSGACC: dev->rregs[ESP_RINTR] |= INTR_DC; dev->rregs[ESP_RSEQ] = 0; @@ -1160,6 +1505,7 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val) static void esp_pci_dma_memory_rw(esp_t *dev, uint8_t *buf, uint32_t len, int dir) { + uint32_t addr; int expected_dir; if (dev->dma_regs[DMA_CMD] & DMA_CMD_DIR) @@ -1174,14 +1520,15 @@ esp_pci_dma_memory_rw(esp_t *dev, uint8_t *buf, uint32_t len, int dir) return; } + addr = dev->dma_regs[DMA_WAC]; if (dev->dma_regs[DMA_WBC] < len) len = dev->dma_regs[DMA_WBC]; - if (expected_dir) { - dma_bm_write(dev->dma_regs[DMA_SPA], buf, len, 4); - } else { - dma_bm_read(dev->dma_regs[DMA_SPA], buf, len, 4); - } + if (expected_dir) + dma_bm_write(addr, buf, len, 4); + else + dma_bm_read(addr, buf, len, 4); + esp_log("DMA: Address = %08X, Length = %08X (%02X %02X %02X %02X -> %02X %02X %02X %02X)\n", dev->dma_regs[DMA_SPA], len, ram[dev->dma_regs[DMA_SPA]], ram[dev->dma_regs[DMA_SPA] + 1], ram[dev->dma_regs[DMA_SPA] + 2], ram[dev->dma_regs[DMA_SPA] + 3], buf[0], buf[1], buf[2], buf[3]); @@ -1201,13 +1548,10 @@ esp_pci_dma_read(esp_t *dev, uint16_t saddr) ret = dev->dma_regs[saddr]; if (saddr == DMA_STAT) { - if (dev->rregs[ESP_RSTAT] & STAT_INT) { - ret |= DMA_STAT_SCSIINT; - esp_log("ESP PCI DMA Read SCSI interrupt issued\n"); - } if (!(dev->sbac & SBAC_STATUS)) { dev->dma_regs[DMA_STAT] &= ~(DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE); esp_log("ESP PCI DMA Read done cleared\n"); + esp_pci_update_irq(dev); } } @@ -1230,6 +1574,7 @@ esp_pci_dma_write(esp_t *dev, uint16_t saddr, uint32_t val) esp_log("PCI DMA disable\n"); break; case 1: /*BLAST*/ + dev->dma_regs[DMA_STAT] |= DMA_STAT_BCMBLT; break; case 2: /*ABORT*/ scsi_device_command_stop(&scsi_devices[dev->bus][dev->id]); @@ -1256,6 +1601,7 @@ esp_pci_dma_write(esp_t *dev, uint16_t saddr, uint32_t val) /* clear some bits on write */ mask = DMA_STAT_ERROR | DMA_STAT_ABORT | DMA_STAT_DONE; dev->dma_regs[DMA_STAT] &= ~(val & mask); + esp_pci_update_irq(dev); } break; @@ -1628,9 +1974,6 @@ dc390_load_eeprom(esp_t *dev) } } -uint8_t esp_pci_regs[256]; -bar_t esp_pci_bar[2]; - static uint8_t esp_pci_read(UNUSED(int func), int addr, void *priv) { @@ -1641,7 +1984,7 @@ esp_pci_read(UNUSED(int func), int addr, void *priv) switch (addr) { case 0x00: // esp_log("ESP PCI: Read DO line = %02x\n", dev->eeprom.out); - if (!dev->has_bios) + if (!dev->has_bios || dev->local) return 0x22; else { if (dev->eeprom.out) @@ -1651,6 +1994,7 @@ esp_pci_read(UNUSED(int func), int addr, void *priv) return 2; } } + break; case 0x01: return 0x10; case 0x02: @@ -1703,6 +2047,7 @@ esp_pci_read(UNUSED(int func), int addr, void *priv) return PCI_INTA; case 0x40 ... 0x4f: + esp_log("ESP PCI: Read value %02X to register %02X, ID=%d\n", esp_pci_regs[addr], addr, dev->id); return esp_pci_regs[addr]; default: @@ -1722,15 +2067,17 @@ esp_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) // esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); - if ((addr >= 0x80) && (addr <= 0xFF)) { - if (addr == 0x80) { - eesk = val & 0x80 ? 1 : 0; - eedi = val & 0x40 ? 1 : 0; - dc390_write_eeprom(dev, 1, eesk, eedi); - } else if (addr == 0xc0) - dc390_write_eeprom(dev, 0, 0, 0); - // esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); - return; + if (!dev->local) { + if ((addr >= 0x80) && (addr <= 0xFF)) { + if (addr == 0x80) { + eesk = val & 0x80 ? 1 : 0; + eedi = val & 0x40 ? 1 : 0; + dc390_write_eeprom(dev, 1, eesk, eedi); + } else if (addr == 0xc0) + dc390_write_eeprom(dev, 0, 0, 0); + // esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr); + return; + } } switch (addr) { @@ -1809,6 +2156,7 @@ esp_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) return; case 0x40 ... 0x4f: + esp_log("ESP PCI: Write value %02X to register %02X, ID=%i.\n", val, addr, dev->id); esp_pci_regs[addr] = val; return; @@ -1827,6 +2175,7 @@ dc390_init(UNUSED(const device_t *info)) dev->bus = scsi_get_bus(); + dev->local = info->local; dev->mca = 0; fifo8_create(&dev->fifo, ESP_FIFO_SZ); @@ -1843,23 +2192,27 @@ dc390_init(UNUSED(const device_t *info)) dev->has_bios = device_get_config_int("bios"); if (dev->has_bios) { dev->BIOSBase = 0xd0000; - rom_init(&dev->bios, DC390_ROM, 0xd0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (dev->local) { + ;//rom_init(&dev->bios, AM53C974_ROM, 0xd0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } else + rom_init(&dev->bios, DC390_ROM, 0xd0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); } /* Enable our BIOS space in PCI, if needed. */ - if (dev->has_bios) { + if (dev->has_bios) esp_pci_bar[1].addr = 0xffff0000; - } else { + else esp_pci_bar[1].addr = 0; - } if (dev->has_bios) esp_bios_disable(dev); - dev->nvr_path = "dc390.nvr"; + if (!dev->local) { + sprintf(dev->nvr_path, "dc390_%i.nvr", device_get_instance()); - /* Load the serial EEPROM. */ - dc390_load_eeprom(dev); + /* Load the serial EEPROM. */ + dc390_load_eeprom(dev); + } esp_pci_hard_reset(dev); @@ -2092,6 +2445,20 @@ const device_t dc390_pci_device = { .config = bios_enable_config }; +const device_t am53c974_pci_device = { + .name = "AMD 53c974 PCI", + .internal_name = "am53c974", + .flags = DEVICE_PCI, + .local = 1, + .init = dc390_init, + .close = esp_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t ncr53c90a_mca_device = { .name = "NCR 53c90a MCA", .internal_name = "ncr53c90a", diff --git a/src/sio/CMakeLists.txt b/src/sio/CMakeLists.txt index dff0fcd0f7..6106871bc3 100644 --- a/src/sio/CMakeLists.txt +++ b/src/sio/CMakeLists.txt @@ -9,18 +9,39 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(sio OBJECT sio_acc3221.c sio_ali5123.c sio_f82c710.c sio_82091aa.c - sio_fdc37c6xx.c sio_fdc37c67x.c sio_fdc37c669.c sio_fdc37c93x.c sio_fdc37m60x.c +add_library(sio OBJECT + sio_acc3221.c + sio_ali5123.c + sio_f82c710.c + sio_82091aa.c + sio_fdc37c6xx.c + sio_fdc37c67x.c + sio_fdc37c669.c + sio_fdc37c93x.c + sio_fdc37m60x.c sio_it86x1f.c - sio_pc87306.c sio_pc87307.c sio_pc87309.c sio_pc87310.c sio_pc87311.c sio_pc87332.c - sio_prime3b.c sio_prime3c.c - sio_w83787f.c sio_w83877f.c sio_w83977f.c - sio_um8663f.c sio_um8669f.c - sio_vt82c686.c) + sio_pc87306.c + sio_pc87307.c + sio_pc87309.c + sio_pc87310.c + sio_pc87311.c + sio_pc87332.c + sio_prime3b.c + sio_prime3c.c + sio_w83787f.c + sio_w83877f.c + sio_w83977f.c + sio_um8663f.c + sio_um8669f.c + sio_vl82c113.c + sio_vt82c686.c +) if(SIO_DETECT) target_sources(sio PRIVATE sio_detect.c) diff --git a/src/sio/sio_fdc37c93x.c b/src/sio/sio_fdc37c93x.c index 97fcb3fbda..a0152c34a3 100644 --- a/src/sio/sio_fdc37c93x.c +++ b/src/sio/sio_fdc37c93x.c @@ -32,6 +32,7 @@ #include <86box/fdd.h> #include <86box/fdc.h> #include <86box/keyboard.h> +#include <86box/machine.h> #include <86box/nvr.h> #include <86box/apm.h> #include <86box/acpi.h> @@ -131,7 +132,8 @@ fdc37c93x_gpio_read(uint16_t port, void *priv) const fdc37c93x_t *dev = (fdc37c93x_t *) priv; uint8_t ret = 0xff; - ret = dev->gpio_regs[port & 1]; + if (strcmp(machine_get_internal_name(), "vectra54")) + ret = dev->gpio_regs[port & 1]; return ret; } @@ -211,7 +213,8 @@ fdc37c93x_nvr_pri_handler(fdc37c93x_t *dev) { uint8_t local_enable = !!dev->ld_regs[6][0x30]; - local_enable &= ((dev->ld_regs[6][0xf0] & 0x90) != 0x80); + if (dev->chip_id != 0x02) + local_enable &= ((dev->ld_regs[6][0xf0] & 0x90) != 0x80); nvr_at_handler(0, 0x70, dev->nvr); if (local_enable) @@ -441,9 +444,9 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) return; else switch (dev->regs[7]) { - case 0x01: - case 0x02: - return; + // case 0x01: + // case 0x02: + // return; case 0x06: if (!dev->has_nvr) return; @@ -495,7 +498,8 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) break; case 0x27: - fdc37c93x_superio_handler(dev); + if (dev->chip_id != 0x02) + fdc37c93x_superio_handler(dev); break; default: @@ -617,12 +621,13 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) case 0x30: if (valxor) { fdc37c93x_nvr_pri_handler(dev); - fdc37c93x_nvr_sec_handler(dev); + if (dev->chip_id != 0x02) + fdc37c93x_nvr_sec_handler(dev); } break; case 0x62: case 0x63: - if (valxor) + if ((dev->chip_id != 0x02) && valxor) fdc37c93x_nvr_sec_handler(dev); break; case 0xf0: @@ -631,7 +636,9 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) nvr_lock_set(0xa0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x02), dev->nvr); nvr_lock_set(0xc0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x04), dev->nvr); nvr_lock_set(0xe0, 0x20, !!(dev->ld_regs[6][dev->cur_reg] & 0x08), dev->nvr); - if (dev->ld_regs[6][dev->cur_reg] & 0x80) + if ((dev->chip_id == 0x02) && (dev->ld_regs[6][dev->cur_reg] & 0x80)) + nvr_bank_set(0, 1, dev->nvr); + else if ((dev->chip_id != 0x02) && (dev->ld_regs[6][dev->cur_reg] & 0x80)) switch ((dev->ld_regs[6][dev->cur_reg] >> 4) & 0x07) { default: case 0x00: @@ -663,11 +670,13 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv) } else { nvr_bank_set(0, 0, dev->nvr); - nvr_bank_set(1, 0xff, dev->nvr); + if (dev->chip_id != 0x02) + nvr_bank_set(1, 0xff, dev->nvr); } fdc37c93x_nvr_pri_handler(dev); - fdc37c93x_nvr_sec_handler(dev); + if (dev->chip_id != 0x02) + fdc37c93x_nvr_sec_handler(dev); } break; @@ -786,8 +795,10 @@ fdc37c93x_reset(fdc37c93x_t *dev) dev->regs[0x21] = 0x01; dev->regs[0x22] = 0x39; dev->regs[0x24] = 0x04; - dev->regs[0x26] = dev->port_370 ? 0x70 : 0xF0; - dev->regs[0x27] = 0x03; + if (dev->chip_id != 0x02) { + dev->regs[0x26] = dev->port_370 ? 0x70 : 0xF0; + dev->regs[0x27] = 0x03; + } for (uint8_t i = 0; i < 11; i++) memset(dev->ld_regs[i], 0, 256); @@ -846,7 +857,9 @@ fdc37c93x_reset(fdc37c93x_t *dev) /* Logical device 6: RTC */ dev->ld_regs[6][0x30] = 0; - dev->ld_regs[6][0x63] = (dev->has_nvr) ? 0x70 : 0x00; + dev->ld_regs[6][0x60] = 0x70; + if (dev->chip_id != 0x02) + dev->ld_regs[6][0x63] = (dev->has_nvr) ? 0x70 : 0x00; dev->ld_regs[6][0xF0] = 0; dev->ld_regs[6][0xF4] = 3; @@ -888,7 +901,8 @@ fdc37c93x_reset(fdc37c93x_t *dev) fdc37c93x_kbc_handler(dev); - fdc37c93x_superio_handler(dev); + if (dev->chip_id != 0x02) + fdc37c93x_superio_handler(dev); dev->locked = 0; } @@ -982,6 +996,13 @@ fdc37c93x_init(const device_t *info) fdc37c93x_reset(dev); + if (dev->chip_id == 0x02) { + io_sethandler(0x03f0, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + io_sethandler(0x0370, 0x0002, + fdc37c93x_read, NULL, NULL, fdc37c93x_write, NULL, NULL, dev); + } + return dev; } @@ -1013,6 +1034,20 @@ const device_t fdc37c931apm_compaq_device = { .config = NULL }; +const device_t fdc37c932_device = { + .name = "SMC FDC37C932 Super I/O", + .internal_name = "fdc37c932", + .flags = 0, + .local = 0x02, + .init = fdc37c93x_init, + .close = fdc37c93x_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + const device_t fdc37c932fr_device = { .name = "SMC FDC37C932FR Super I/O", .internal_name = "fdc37c932fr", diff --git a/src/sio/sio_vl82c113.c b/src/sio/sio_vl82c113.c new file mode 100644 index 0000000000..6a02ef3596 --- /dev/null +++ b/src/sio/sio_vl82c113.c @@ -0,0 +1,163 @@ +/* + * 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 VLSI VL82c113 Combination I/O Chip. + * + * Authors: Miran Grca, + * + * Copyright 2024 Miran Grca. + */ +#include +#include +#include +#include +#include +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/nvr.h> +#include <86box/sio.h> + +typedef struct vl82c113_t { + uint8_t index; + uint8_t nvr_enabled; + uint8_t regs[3]; + uint8_t pad; + uint16_t nvr_base; + int cur_reg; + nvr_t *nvr; + void *kbc; +} vl82c113_t; + +static void +vl82c113_nvr_handler(vl82c113_t *dev) +{ + const uint8_t nvr_enabled = (dev->regs[0x00]) & 0x01; + const uint16_t nvr_base = ((dev->regs[0x01] << 8) | dev->regs[0x00]) & 0xfffe; + + if ((nvr_enabled != dev->nvr_enabled) || (nvr_base != dev->nvr_base)) { + if (dev->nvr_enabled && (dev->nvr_base != 0x0000)) + nvr_at_handler(0, dev->nvr_base, dev->nvr); + + dev->nvr_enabled = nvr_enabled; + dev->nvr_base = nvr_base; + + if (dev->nvr_enabled && (dev->nvr_base != 0x0000)) + nvr_at_handler(1, dev->nvr_base, dev->nvr); + } +} + +static void +vl82c113_out(uint16_t port, uint8_t val, void *priv) +{ + vl82c113_t *dev = (vl82c113_t *) priv; + + if (port == 0xec) + dev->index = val; + else if ((dev->index >= 0x1b) && (dev->index <= 0x1d)) { + const uint8_t index = dev->index - 0x1b; + const uint8_t valxor = dev->regs[index] ^ val; + + dev->regs[index] = val; + + switch (index) { + default: + break; + + case 0x00: + case 0x01: + if (valxor) + vl82c113_nvr_handler(dev); + break; + + case 0x02: + if (valxor & 0x02) + kbc_at_set_ps2(dev->kbc, !(val & 0x02)); + break; + } + } +} + +static uint8_t +vl82c113_in(uint16_t port, void *priv) +{ + const vl82c113_t *dev = (vl82c113_t *) priv; + uint8_t ret = 0xff; + + if (port == 0xed) { + if ((dev->index >= 0x1b) && (dev->index <= 0x1d)) + ret = dev->regs[dev->index - 0x1b]; + else if (dev->index == 0x1f) + /* REVID */ + ret = 0xc0; + } + + return ret; +} + +static void +vl82c113_reset(void *priv) +{ + vl82c113_t *dev = (vl82c113_t *) priv; + + memset(dev->regs, 0x00, sizeof(dev->regs)); + + dev->regs[0x00] = 0x71; + dev->regs[0x01] = 0x00; + + dev->regs[0x02] = 0xc3; + + kbc_at_set_ps2(dev->kbc, 0); + + vl82c113_nvr_handler(dev); +} + +static void +vl82c113_close(void *priv) +{ + vl82c113_t *dev = (vl82c113_t *) priv; + + free(dev); +} + +static void * +vl82c113_init(const device_t *info) +{ + vl82c113_t *dev = (vl82c113_t *) calloc(1, sizeof(vl82c113_t)); + + dev->nvr = device_add(&at_nvr_device); + + dev->nvr_enabled = 1; + dev->nvr_base = 0x0070; + + /* Commands are standard. */ + dev->kbc = device_add(&keyboard_at_device); + + vl82c113_reset(dev); + + io_sethandler(0x00ec, 0x0002, vl82c113_in, NULL, NULL, vl82c113_out, NULL, NULL, dev); + + return dev; +} + +const device_t vl82c113_device = { + .name = "VLSI VL82c113 Combination I/O", + .internal_name = "vl82c113", + .flags = 0, + .local = 0, + .init = vl82c113_init, + .close = vl82c113_close, + .reset = vl82c113_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index f67630c475..9fbdd6ac19 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -9,16 +9,49 @@ # CMake build script. # # Authors: David Hrdlička, +# Jasmine Iwanek, # # Copyright 2020-2021 David Hrdlička. +# Copyright 2024 Jasmine Iwanek. # -add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_resid.cc - midi.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c - snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c - snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c - snd_emu8k.c snd_mpu401.c snd_pas16.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c - snd_optimc.c esfmu/esfm.c esfmu/esfm_registers.c snd_opl_esfm.c) +add_library(snd OBJECT + sound.c + snd_opl.c + snd_opl_nuked.c + snd_opl_ymfm.cpp + snd_resid.cpp + midi.c + snd_speaker.c + snd_pssj.c + snd_lpt_dac.c + snd_ac97_codec.c + snd_ac97_via.c + snd_lpt_dss.c + snd_ps1.c + snd_adlib.c + snd_adlibgold.c + snd_ad1848.c + snd_audiopci.c + snd_azt2316a.c + snd_cms.c + snd_cmi8x38.c + snd_cs423x.c + snd_gus.c + snd_sb.c + snd_sb_dsp.c + snd_emu8k.c + snd_mpu401.c + snd_pas16.c + snd_sn76489.c + snd_ssi2001.c + snd_wss.c + snd_ym7128.c + snd_optimc.c + esfmu/esfm.c + esfmu/esfm_registers.c + snd_opl_esfm.c +) if(OPENAL) if(VCPKG_TOOLCHAIN) @@ -90,6 +123,13 @@ if(FLUIDSYNTH) target_link_libraries(86Box PkgConfig::FLUIDSYNTH) if(STATIC_BUILD) target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp) + if(WIN32) + add_compile_definitions(FLUIDSYNTH_NOT_A_DLL) + + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + target_link_libraries(86Box psapi) + endif() + endif() endif() target_compile_definitions(snd PRIVATE USE_FLUIDSYNTH) diff --git a/src/sound/midi.c b/src/sound/midi.c index bb107acbf9..9edf0a2aad 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -71,62 +71,34 @@ typedef struct const device_t *device; } MIDI_OUT_DEVICE, MIDI_IN_DEVICE; -static const device_t midi_out_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const MIDI_OUT_DEVICE devices[] = { // clang-format off - { &midi_out_none_device }, + { &device_none }, #ifdef USE_FLUIDSYNTH - { &fluidsynth_device }, -#endif + { &fluidsynth_device }, +#endif /* USE_FLUIDSYNTH */ #ifdef USE_MUNT - { &mt32_old_device }, - { &mt32_new_device }, - { &cm32l_device }, - { &cm32ln_device }, -#endif + { &mt32_old_device }, + { &mt32_new_device }, + { &cm32l_device }, + { &cm32ln_device }, +#endif /*USE_MUNT */ #ifdef USE_RTMIDI - { &rtmidi_output_device }, -#endif -#if defined(DEV_BRANCH) && defined(USE_OPL4ML) - { &opl4_midi_device }, -#endif - { NULL } + { &rtmidi_output_device }, +#endif /* USE_RTMIDI */ +#ifdef USE_OPL4ML + { &opl4_midi_device }, +#endif /* USE_OPL4ML */ + { NULL } // clang-format on }; -static const device_t midi_in_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const MIDI_IN_DEVICE midi_in_devices[] = { // clang-format off - { &midi_in_none_device }, + { &device_none }, #ifdef USE_RTMIDI { &rtmidi_input_device }, -#endif +#endif /* USE_RTMIDI */ { NULL } // clang-format on }; @@ -369,7 +341,7 @@ midi_raw_out_byte(uint8_t val) else if ((midi_out->midi_sysex_data[5] == 0x10) && (midi_out->midi_sysex_data[6] == 0x00) && (midi_out->midi_sysex_data[7] == 0x01)) midi_out->midi_sysex_delay = 30; /* Dark Sun 1 */ else - midi_out->midi_sysex_delay = (unsigned int) (((float) (midi_out->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2; + midi_out->midi_sysex_delay = (unsigned int) (((double) (midi_out->midi_pos) * 1.25) / 3.125) + 2; midi_out->midi_sysex_start = plat_get_ticks(); } @@ -612,3 +584,10 @@ midi_in_sysex(uint8_t *buffer, uint32_t len) break; } } + +void +midi_reset(void) +{ + if (midi_out && midi_out->m_out_device && midi_out->m_out_device->reset) + midi_out->m_out_device->reset(); +} diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index c1b9956d08..f8c7964f7b 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -7,7 +7,6 @@ #ifdef __unix__ # include #endif -#define FLUIDSYNTH_NOT_A_DLL #include #include <86box/86box.h> diff --git a/src/sound/resid-fp/AUTHORS b/src/sound/resid-fp/AUTHORS index cd2ca3fccd..b04ee0f010 100644 --- a/src/sound/resid-fp/AUTHORS +++ b/src/sound/resid-fp/AUTHORS @@ -1,4 +1,6 @@ -Authors of reSID. +Authors of reSIDfp. Dag Lem: Designed and programmed complete emulation engine. -Antti S. Lankila: Support 6581 filter distortion, envelope & voice nonlinearities, output amp clipping effects. +Antti S. Lankila: Distortion simulation and calculation of combined waveforms +Ken Händel: source code conversion to Java +Leandro Nini: port to c++, merge with reSID 1.0 diff --git a/src/sound/resid-fp/CMakeLists.txt b/src/sound/resid-fp/CMakeLists.txt index 699fcae54d..5246dd73b5 100644 --- a/src/sound/resid-fp/CMakeLists.txt +++ b/src/sound/resid-fp/CMakeLists.txt @@ -13,7 +13,8 @@ # Copyright 2020-2021 David Hrdlička. # -add_library(resid-fp STATIC convolve-sse.cc convolve.cc envelope.cc extfilt.cc - filter.cc pot.cc sid.cc voice.cc wave.cc wave6581_PST.cc - wave6581_PS_.cc wave6581_P_T.cc wave6581__ST.cc wave8580_PST.cc - wave8580_PS_.cc wave8580_P_T.cc wave8580__ST.cc) \ No newline at end of file +add_library(resid-fp STATIC Dac.cpp EnvelopeGenerator.cpp ExternalFilter.cpp + Filter.cpp Filter6581.cpp Filter8580.cpp FilterModelConfig.cpp + FilterModelConfig6581.cpp FilterModelConfig8580.cpp + Integrator6581.cpp Integrator8580.cpp OpAmp.cpp SID.cpp + Spline.cpp WaveformCalculator.cpp WaveformGenerator.cpp resample/SincResampler.cpp) diff --git a/src/sound/resid-fp/COPYING b/src/sound/resid-fp/COPYING index d60c31a97a..d159169d10 100644 --- a/src/sound/resid-fp/COPYING +++ b/src/sound/resid-fp/COPYING @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions: License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) year name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names: This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General +library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diff --git a/src/sound/resid-fp/ChangeLog b/src/sound/resid-fp/ChangeLog deleted file mode 100644 index c12e828b93..0000000000 --- a/src/sound/resid-fp/ChangeLog +++ /dev/null @@ -1,136 +0,0 @@ -2008-12-05 Antti S. Lankila - - * Sync against V27 patch version. Filter updates described below. - - * Reduce Q maximum to 2.2 or so. This may still be slightly too much, - but it's hard to say exactly... - - * Arrange for about 3 dB boost of lowpass output that is independent - of state variable mixing or other feedback. This seems to produce - the right kind of sounds for songs like AMJ's Blasphemy. - - * Assume that bp is slightly louder than bp (= more distorted). - This seems to help against very large number of songs which sport - lead sounds and effects distorted in a smooth, bassy way. - - * Parameter tuneup. - -2008-10-31 Antti S. Lankila - - * Sync against V25 patch version. Filter updates described below. - - * Tweak filter algorithm to do some state variable mixing in the - 6581 code path. This corresponds with assumed output impedance of - the SID "amplifiers", and is separate effect to the output strip - backmixing. - - * Retire the V24 attempt of dynamically adjusting BP distortion - threshold. It doesn't really seem to work. - - * Increase Q value maximum to 2.5. This may be too much, but it sounds - fine to me. - - * JT's Star Ball was very distorted when played by V24. This related - to the hardclipping I had assumed to occur in the filter output amp, - but maybe that theory is incorrect. I now only add distortion to the - unfiltered voice path, but I'm not happy about it. - -2008-08-29 Antti S. Lankila - - * Optimized resampling to be about 2x faster through using aliasing - to increase passband width and hence reduce FIR length. - - * Fixed some valgrind warnings. - - * Added nuke_denormals() method to periodically flush these to zero, as - this can only be done for SSE registers by the FPU and we can't use - any in order to support CPUs older than P3. - - * Marco, Hannu and me developed a runtime switching system - that detects SSE from cpuinfo and calls some SSE routines when they - are compiled in and the CPU can support them. We lost only very - little performance, but gained compatibility to very, very old - hardware. - - * The old code for ST_lockup proved unnecessary, so it is now removed. - -2008-08-21 Antti S. Lankila - - * Fixed a bug where nonlinearity setting appeared to get lost, and - kenchis discovered further bugs in it. Oh well. - - * I removed a lot of code associated with the lower quality modes of - ReSID, and only left the 1 MHz clock routines. Analysis shows that the - filter code is a major culprit, but the digital side emulation is not - completely cheap, either. I already added some small hacks to optimize - it, and I now think about reinjecting pieces of those clocking modes - that run the analog parts with reduced accuracy. - - * I defined type4 filters based on equation of straight line. These are - characterized by parameters k and b, and the equation is - freq = k * fc. Strictly speaking, straight line is not 100 % - accurate, and a 2nd degree component would help, but based on - measurements against two of Trurl's 8580s, the maximum error - introduced using linear approximation is mere 3 %. - -2008-08-10 Antti S. Lankila - - * I ripped off Type1 definitions from the filter, and the spline.h - and PointPlotter were unnecessary and so removed. - - * I also added a bit of hardclipping in the output that seems to be - required to get Fred Gray's Break Thru. This might not occur so - strongly on all chips, so it should probably be added as a proper - tunable. For now, I just settled for a slight effect to collect - feedback. - -2008-07-15 Antti S. Lankila - - * This release is a bit slower than usual. The culprit is the changes in - voice.h where a new kinked-dac style calculation is used to simulate - the nonlinear shape of the waveform outputs. The cost of the new - calculation varies by song as I was lazy and only cached the result of - previous calculation, so speed depends on the pitch of the waveforms - and the precise waveform chosen. - - * exp() is back, but this time it is implemented as an integer - calculation according to Schraudolph's paper "A Fast, Compact - Approximation of the Exponential Function". Using near-proper exp() - simplified the distortion algorithm. I think it all sounds much better - now. - - * A new effect where I mix bp-hp and lp-bp together by their difference - to simulate a small resistor between them appears to improve SidRiders - and several other songs, largerly eliminating some types of hard - distortion sounds that do not occur on the chip. It also helped - Mechanicus. I am trying to understand where this term comes from... - -2008-07-09 Antti S. Lankila - - * I now have somewhat less arbitrary values for the distortion - tunables. They are now related to the relative signal levels in the - simulation. I'm still sorting out the particulars of the values I - ended up with ("why 128 instead of 256"). - -2008-03-02 Antti S. Lankila - - * Exposed the filter at sid.cc to callers through get_filter() - method, and fixed a few types. - -2008-02-19 Antti S. Lankila - - * For some reason ReSID code adjusted the external filter frequency - based on calculated passband, while in the real C64 the filter is - fixed to about 16 kHz. - -2008-02-06 Antti S. Lankila - - * I got interested to improve ReSID after chatting with Kevtris. He is - aiming to replicate the filter using analog hardware. He has the EE - experience that I have sorely lacked and made an infinitely valuable - contribution by telling me exactly how the distortion works. - -2004-06-11 Dag Lem - - * Version 0.16 released. (From this point forwards, read - ../resid/ChangeLog.) diff --git a/src/sound/resid-fp/Dac.cpp b/src/sound/resid-fp/Dac.cpp new file mode 100644 index 0000000000..0665da8177 --- /dev/null +++ b/src/sound/resid-fp/Dac.cpp @@ -0,0 +1,123 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2016 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "Dac.h" + +namespace reSIDfp +{ + +Dac::Dac(unsigned int bits) : + dac(new double[bits]), + dacLength(bits) +{} + +Dac::~Dac() +{ + delete [] dac; +} + +double Dac::getOutput(unsigned int input) const +{ + double dacValue = 0.; + + for (unsigned int i = 0; i < dacLength; i++) + { + if ((input & (1 << i)) != 0) + { + dacValue += dac[i]; + } + } + + return dacValue; +} + +void Dac::kinkedDac(ChipModel chipModel) +{ + const double R_INFINITY = 1e6; + + // Non-linearity parameter, 8580 DACs are perfectly linear + const double _2R_div_R = chipModel == MOS6581 ? 2.20 : 2.00; + + // 6581 DACs are not terminated by a 2R resistor + const bool term = chipModel == MOS8580; + + // Calculate voltage contribution by each individual bit in the R-2R ladder. + for (unsigned int set_bit = 0; set_bit < dacLength; set_bit++) + { + double Vn = 1.; // Normalized bit voltage. + double R = 1.; // Normalized R + const double _2R = _2R_div_R * R; // 2R + double Rn = term ? // Rn = 2R for correct termination, + _2R : R_INFINITY; // INFINITY for missing termination. + + unsigned int bit; + + // Calculate DAC "tail" resistance by repeated parallel substitution. + for (bit = 0; bit < set_bit; bit++) + { + Rn = (Rn == R_INFINITY) ? + R + _2R : + R + (_2R * Rn) / (_2R + Rn); // R + 2R || Rn + } + + // Source transformation for bit voltage. + if (Rn == R_INFINITY) + { + Rn = _2R; + } + else + { + Rn = (_2R * Rn) / (_2R + Rn); // 2R || Rn + Vn = Vn * Rn / _2R; + } + + // Calculate DAC output voltage by repeated source transformation from + // the "tail". + + for (++bit; bit < dacLength; bit++) + { + Rn += R; + const double I = Vn / Rn; + Rn = (_2R * Rn) / (_2R + Rn); // 2R || Rn + Vn = Rn * I; + } + + dac[set_bit] = Vn; + } + + // Normalize to integerish behavior + double Vsum = 0.; + + for (unsigned int i = 0; i < dacLength; i++) + { + Vsum += dac[i]; + } + + Vsum /= 1 << dacLength; + + for (unsigned int i = 0; i < dacLength; i++) + { + dac[i] /= Vsum; + } +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/Dac.h b/src/sound/resid-fp/Dac.h new file mode 100644 index 0000000000..35bc0b2cab --- /dev/null +++ b/src/sound/resid-fp/Dac.h @@ -0,0 +1,111 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2016 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef DAC_H +#define DAC_H + +#include "siddefs-fp.h" + +namespace reSIDfp +{ + +/** + * Estimate DAC nonlinearity. + * The SID DACs are built up as R-2R ladder as follows: + * + * n n-1 2 1 0 VGND + * | | | | | | Termination + * 2R 2R 2R 2R 2R 2R only for + * | | | | | | MOS 8580 + * Vo -o-R-o-R-...-o-R-o-R-- --+ + * + * + * All MOS 6581 DACs are missing a termination resistor at bit 0. This causes + * pronounced errors for the lower 4 - 5 bits (e.g. the output for bit 0 is + * actually equal to the output for bit 1), resulting in DAC discontinuities + * for the lower bits. + * In addition to this, the 6581 DACs exhibit further severe discontinuities + * for higher bits, which may be explained by a less than perfect match between + * the R and 2R resistors, or by output impedance in the NMOS transistors + * providing the bit voltages. A good approximation of the actual DAC output is + * achieved for 2R/R ~ 2.20. + * + * The MOS 8580 DACs, on the other hand, do not exhibit any discontinuities. + * These DACs include the correct termination resistor, and also seem to have + * very accurately matched R and 2R resistors (2R/R = 2.00). + * + * On the 6581 the output of the waveform and envelope DACs go through + * a voltage follower built with two NMOS: + * + * Vdd + * + * | + * |-+ + * Vin -------| T1 (enhancement-mode) + * |-+ + * | + * o-------- Vout + * | + * |-+ + * +---| T2 (depletion-mode) + * | |-+ + * | | + * + * GND GND + */ +class Dac +{ +private: + /// analog values + double * const dac; + + /// the dac array length + const unsigned int dacLength; + +public: + /** + * Initialize DAC model. + * + * @param bits the number of input bits + */ + Dac(unsigned int bits); + ~Dac(); + + /** + * Build DAC model for specific chip. + * + * @param chipModel 6581 or 8580 + */ + void kinkedDac(ChipModel chipModel); + + /** + * Get the Vo output for a given combination of input bits. + * + * @param input the digital input + * @return the analog output value + */ + double getOutput(unsigned int input) const; +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/EnvelopeGenerator.cpp b/src/sound/resid-fp/EnvelopeGenerator.cpp new file mode 100644 index 0000000000..af636ac7f4 --- /dev/null +++ b/src/sound/resid-fp/EnvelopeGenerator.cpp @@ -0,0 +1,155 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2018 VICE Project + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define ENVELOPEGENERATOR_CPP + +#include "EnvelopeGenerator.h" + +namespace reSIDfp +{ + +/** + * Lookup table to convert from attack, decay, or release value to rate + * counter period. + * + * The rate counter is a 15 bit register which is left shifted each cycle. + * When the counter reaches a specific comparison value, + * the envelope counter is incremented (attack) or decremented + * (decay/release) and the rate counter is resetted. + * + * see [kevtris.org](http://blog.kevtris.org/?p=13) + */ +const unsigned int EnvelopeGenerator::adsrtable[16] = +{ + 0x007f, + 0x3000, + 0x1e00, + 0x0660, + 0x0182, + 0x5573, + 0x000e, + 0x3805, + 0x2424, + 0x2220, + 0x090c, + 0x0ecd, + 0x010e, + 0x23f7, + 0x5237, + 0x64a8 +}; + +void EnvelopeGenerator::reset() +{ + // counter is not changed on reset + envelope_pipeline = 0; + + state_pipeline = 0; + + attack = 0; + decay = 0; + sustain = 0; + release = 0; + + gate = false; + + resetLfsr = true; + + exponential_counter = 0; + exponential_counter_period = 1; + new_exponential_counter_period = 0; + + state = RELEASE; + counter_enabled = true; + rate = adsrtable[release]; +} + +void EnvelopeGenerator::writeCONTROL_REG(unsigned char control) +{ + const bool gate_next = (control & 0x01) != 0; + + if (gate_next != gate) + { + gate = gate_next; + + // The rate counter is never reset, thus there will be a delay before the + // envelope counter starts counting up (attack) or down (release). + + if (gate_next) + { + // Gate bit on: Start attack, decay, sustain. + next_state = ATTACK; + state_pipeline = 2; + + if (resetLfsr || (exponential_pipeline == 2)) + { + envelope_pipeline = (exponential_counter_period == 1) || (exponential_pipeline == 2) ? 2 : 4; + } + else if (exponential_pipeline == 1) + { + state_pipeline = 3; + } + } + else + { + // Gate bit off: Start release. + next_state = RELEASE; + state_pipeline = envelope_pipeline > 0 ? 3 : 2; + } + } +} + +void EnvelopeGenerator::writeATTACK_DECAY(unsigned char attack_decay) +{ + attack = (attack_decay >> 4) & 0x0f; + decay = attack_decay & 0x0f; + + if (state == ATTACK) + { + rate = adsrtable[attack]; + } + else if (state == DECAY_SUSTAIN) + { + rate = adsrtable[decay]; + } +} + +void EnvelopeGenerator::writeSUSTAIN_RELEASE(unsigned char sustain_release) +{ + // From the sustain levels it follows that both the low and high 4 bits + // of the envelope counter are compared to the 4-bit sustain value. + // This has been verified by sampling ENV3. + // + // For a detailed description see: + // http://ploguechipsounds.blogspot.it/2010/11/new-research-on-sid-adsr.html + sustain = (sustain_release & 0xf0) | ((sustain_release >> 4) & 0x0f); + + release = sustain_release & 0x0f; + + if (state == RELEASE) + { + rate = adsrtable[release]; + } +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/EnvelopeGenerator.h b/src/sound/resid-fp/EnvelopeGenerator.h new file mode 100644 index 0000000000..f2aab38743 --- /dev/null +++ b/src/sound/resid-fp/EnvelopeGenerator.h @@ -0,0 +1,419 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2022 Leandro Nini + * Copyright 2018 VICE Project + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef ENVELOPEGENERATOR_H +#define ENVELOPEGENERATOR_H + +#include "siddefs-fp.h" + +namespace reSIDfp +{ + +/** + * A 15 bit [LFSR] is used to implement the envelope rates, in effect dividing + * the clock to the envelope counter by the currently selected rate period. + * + * In addition, another 5 bit counter is used to implement the exponential envelope decay, + * in effect further dividing the clock to the envelope counter. + * The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope counter + * values 255, 93, 54, 26, 14, 6, respectively. + * + * [LFSR]: https://en.wikipedia.org/wiki/Linear_feedback_shift_register + */ +class EnvelopeGenerator +{ +private: + /** + * The envelope state machine's distinct states. In addition to this, + * envelope has a hold mode, which freezes envelope counter to zero. + */ + enum State + { + ATTACK, DECAY_SUSTAIN, RELEASE + }; + +private: + /// XOR shift register for ADSR prescaling. + unsigned int lfsr; + + /// Comparison value (period) of the rate counter before next event. + unsigned int rate; + + /** + * During release mode, the SID approximates envelope decay via piecewise + * linear decay rate. + */ + unsigned int exponential_counter; + + /** + * Comparison value (period) of the exponential decay counter before next + * decrement. + */ + unsigned int exponential_counter_period; + unsigned int new_exponential_counter_period; + + unsigned int state_pipeline; + + /// + unsigned int envelope_pipeline; + + unsigned int exponential_pipeline; + + /// Current envelope state + State state; + State next_state; + + /// Whether counter is enabled. Only switching to ATTACK can release envelope. + bool counter_enabled; + + /// Gate bit + bool gate; + + /// + bool resetLfsr; + + /// The current digital value of envelope output. + unsigned char envelope_counter; + + /// Attack register + unsigned char attack; + + /// Decay register + unsigned char decay; + + /// Sustain register + unsigned char sustain; + + /// Release register + unsigned char release; + + /// The ENV3 value, sampled at the first phase of the clock + unsigned char env3; + +private: + static const unsigned int adsrtable[16]; + +private: + void set_exponential_counter(); + + void state_change(); + +public: + /** + * SID clocking. + */ + void clock(); + + /** + * Get the Envelope Generator digital output. + */ + unsigned int output() const { return envelope_counter; } + + /** + * Constructor. + */ + EnvelopeGenerator() : + lfsr(0x7fff), + rate(0), + exponential_counter(0), + exponential_counter_period(1), + new_exponential_counter_period(0), + state_pipeline(0), + envelope_pipeline(0), + exponential_pipeline(0), + state(RELEASE), + next_state(RELEASE), + counter_enabled(true), + gate(false), + resetLfsr(false), + envelope_counter(0xaa), + attack(0), + decay(0), + sustain(0), + release(0), + env3(0) + {} + + /** + * SID reset. + */ + void reset(); + + /** + * Write control register. + * + * @param control + * control register value + */ + void writeCONTROL_REG(unsigned char control); + + /** + * Write Attack/Decay register. + * + * @param attack_decay + * attack/decay value + */ + void writeATTACK_DECAY(unsigned char attack_decay); + + /** + * Write Sustain/Release register. + * + * @param sustain_release + * sustain/release value + */ + void writeSUSTAIN_RELEASE(unsigned char sustain_release); + + /** + * Return the envelope current value. + * + * @return envelope counter value + */ + unsigned char readENV() const { return env3; } +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(ENVELOPEGENERATOR_CPP) + +namespace reSIDfp +{ + +RESID_INLINE +void EnvelopeGenerator::clock() +{ + env3 = envelope_counter; + + if (unlikely(new_exponential_counter_period > 0)) + { + exponential_counter_period = new_exponential_counter_period; + new_exponential_counter_period = 0; + } + + if (unlikely(state_pipeline)) + { + state_change(); + } + + if (unlikely(envelope_pipeline != 0) && (--envelope_pipeline == 0)) + { + if (likely(counter_enabled)) + { + if (state == ATTACK) + { + if (++envelope_counter==0xff) + { + next_state = DECAY_SUSTAIN; + state_pipeline = 3; + } + } + else if ((state == DECAY_SUSTAIN) || (state == RELEASE)) + { + if (--envelope_counter==0x00) + { + counter_enabled = false; + } + } + + set_exponential_counter(); + } + } + else if (unlikely(exponential_pipeline != 0) && (--exponential_pipeline == 0)) + { + exponential_counter = 0; + + if (((state == DECAY_SUSTAIN) && (envelope_counter != sustain)) + || (state == RELEASE)) + { + // The envelope counter can flip from 0x00 to 0xff by changing state to + // attack, then to release. The envelope counter will then continue + // counting down in the release state. + // This has been verified by sampling ENV3. + + envelope_pipeline = 1; + } + } + else if (unlikely(resetLfsr)) + { + lfsr = 0x7fff; + resetLfsr = false; + + if (state == ATTACK) + { + // The first envelope step in the attack state also resets the exponential + // counter. This has been verified by sampling ENV3. + exponential_counter = 0; // NOTE this is actually delayed one cycle, not modeled + + // The envelope counter can flip from 0xff to 0x00 by changing state to + // release, then to attack. The envelope counter is then frozen at + // zero; to unlock this situation the state must be changed to release, + // then to attack. This has been verified by sampling ENV3. + + envelope_pipeline = 2; + } + else + { + if (counter_enabled && (++exponential_counter == exponential_counter_period)) + exponential_pipeline = exponential_counter_period != 1 ? 2 : 1; + } + } + + // ADSR delay bug. + // If the rate counter comparison value is set below the current value of the + // rate counter, the counter will continue counting up until it wraps around + // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the + // envelope can constly be stepped. + // This has been verified by sampling ENV3. + + // check to see if LFSR matches table value + if (likely(lfsr != rate)) + { + // it wasn't a match, clock the LFSR once + // by performing XOR on last 2 bits + const unsigned int feedback = ((lfsr << 14) ^ (lfsr << 13)) & 0x4000; + lfsr = (lfsr >> 1) | feedback; + } + else + { + resetLfsr = true; + } +} + +/** + * This is what happens on chip during state switching, + * based on die reverse engineering and transistor level + * emulation. + * + * Attack + * + * 0 - Gate on + * 1 - Counting direction changes + * During this cycle the decay rate is "accidentally" activated + * 2 - Counter is being inverted + * Now the attack rate is correctly activated + * Counter is enabled + * 3 - Counter will be counting upward from now on + * + * Decay + * + * 0 - Counter == $ff + * 1 - Counting direction changes + * The attack state is still active + * 2 - Counter is being inverted + * During this cycle the decay state is activated + * 3 - Counter will be counting downward from now on + * + * Release + * + * 0 - Gate off + * 1 - During this cycle the release state is activated if coming from sustain/decay + * *2 - Counter is being inverted, the release state is activated + * *3 - Counter will be counting downward from now on + * + * (* only if coming directly from Attack state) + * + * Freeze + * + * 0 - Counter == $00 + * 1 - Nothing + * 2 - Counter is disabled + */ +RESID_INLINE +void EnvelopeGenerator::state_change() +{ + state_pipeline--; + + switch (next_state) + { + case ATTACK: + if (state_pipeline == 1) + { + // The decay rate is "accidentally" enabled during first cycle of attack phase + rate = adsrtable[decay]; + } + else if (state_pipeline == 0) + { + state = ATTACK; + // The attack rate is correctly enabled during second cycle of attack phase + rate = adsrtable[attack]; + counter_enabled = true; + } + break; + case DECAY_SUSTAIN: + if (state_pipeline == 0) + { + state = DECAY_SUSTAIN; + rate = adsrtable[decay]; + } + break; + case RELEASE: + if (((state == ATTACK) && (state_pipeline == 0)) + || ((state == DECAY_SUSTAIN) && (state_pipeline == 1))) + { + state = RELEASE; + rate = adsrtable[release]; + } + break; + } +} + +RESID_INLINE +void EnvelopeGenerator::set_exponential_counter() +{ + // Check for change of exponential counter period. + // + // For a detailed description see: + // http://ploguechipsounds.blogspot.it/2010/03/sid-6581r3-adsr-tables-up-close.html + switch (envelope_counter) + { + case 0xff: + case 0x00: + new_exponential_counter_period = 1; + break; + + case 0x5d: + new_exponential_counter_period = 2; + break; + + case 0x36: + new_exponential_counter_period = 4; + break; + + case 0x1a: + new_exponential_counter_period = 8; + break; + + case 0x0e: + new_exponential_counter_period = 16; + break; + + case 0x06: + new_exponential_counter_period = 30; + break; + } +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/ExternalFilter.cpp b/src/sound/resid-fp/ExternalFilter.cpp new file mode 100644 index 0000000000..eac790b31f --- /dev/null +++ b/src/sound/resid-fp/ExternalFilter.cpp @@ -0,0 +1,68 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define EXTERNALFILTER_CPP + +#include "ExternalFilter.h" + +namespace reSIDfp +{ + +/** + * Get the 3 dB attenuation point. + * + * @param res the resistance value in Ohms + * @param cap the capacitance value in Farads + */ +inline double getRC(double res, double cap) +{ + return res * cap; +} + +ExternalFilter::ExternalFilter() : + w0lp_1_s7(0), + w0hp_1_s17(0) +{ + reset(); +} + +void ExternalFilter::setClockFrequency(double frequency) +{ + const double dt = 1. / frequency; + + // Low-pass: R = 10kOhm, C = 1000pF; w0l = dt/(dt+RC) = 1e-6/(1e-6+1e4*1e-9) = 0.091 + // Cutoff 1/2*PI*RC = 1/2*PI*1e4*1e-9 = 15915.5 Hz + w0lp_1_s7 = static_cast((dt / (dt + getRC(10e3, 1000e-12))) * (1 << 7) + 0.5); + + // High-pass: R = 10kOhm, C = 10uF; w0h = dt/(dt+RC) = 1e-6/(1e-6+1e4*1e-5) = 0.00000999 + // Cutoff 1/2*PI*RC = 1/2*PI*1e4*1e-5 = 1.59155 Hz + w0hp_1_s17 = static_cast((dt / (dt + getRC(10e3, 10e-6))) * (1 << 17) + 0.5); +} + +void ExternalFilter::reset() +{ + // State of filter. + Vlp = 0; //1 << (15 + 11); + Vhp = 0; +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/ExternalFilter.h b/src/sound/resid-fp/ExternalFilter.h new file mode 100644 index 0000000000..760ee5c227 --- /dev/null +++ b/src/sound/resid-fp/ExternalFilter.h @@ -0,0 +1,125 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef EXTERNALFILTER_H +#define EXTERNALFILTER_H + +#include "siddefs-fp.h" + +namespace reSIDfp +{ + +/** + * The audio output stage in a Commodore 64 consists of two STC networks, a + * low-pass RC filter with 3 dB frequency 16kHz followed by a DC-blocker which + * acts as a high-pass filter with a cutoff dependent on the attached audio + * equipment impedance. Here we suppose an impedance of 10kOhm resulting + * in a 3 dB attenuation at 1.6Hz. + * To operate properly the 6581 audio output needs a pull-down resistor + *(1KOhm recommended, not needed on 8580) + * + * ~~~ + * 9/12V + * -----+ + * audio| 10k | + * +---o----R---o--------o-----(K) +----- + * out | | | | | |audio + * -----+ R 1k C 1000 | | 10 uF | + * | | pF +-C----o-----C-----+ 10k + * 470 | | + * GND GND pF R 1K | amp + * * * | +----- + * + * GND + * ~~~ + * + * The STC networks are connected with a [BJT] based [common collector] + * used as a voltage follower (featuring a 2SC1815 NPN transistor). + * * The C64c board additionally includes a [bootstrap] condenser to increase + * the input impedance of the common collector. + * + * [BJT]: https://en.wikipedia.org/wiki/Bipolar_junction_transistor + * [common collector]: https://en.wikipedia.org/wiki/Common_collector + * [bootstrap]: https://en.wikipedia.org/wiki/Bootstrapping_(electronics) + */ +class ExternalFilter +{ +private: + /// Lowpass filter voltage + int Vlp; + + /// Highpass filter voltage + int Vhp; + + int w0lp_1_s7; + + int w0hp_1_s17; + +public: + /** + * SID clocking. + * + * @param input + */ + int clock(unsigned short input); + + /** + * Constructor. + */ + ExternalFilter(); + + /** + * Setup of the external filter sampling parameters. + * + * @param frequency the main system clock frequency + */ + void setClockFrequency(double frequency); + + /** + * SID reset. + */ + void reset(); +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(EXTERNALFILTER_CPP) + +namespace reSIDfp +{ + +RESID_INLINE +int ExternalFilter::clock(unsigned short input) +{ + const int Vi = (static_cast(input)<<11) - (1 << (11+15)); + const int dVlp = (w0lp_1_s7 * (Vi - Vlp) >> 7); + const int dVhp = (w0hp_1_s17 * (Vlp - Vhp) >> 17); + Vlp += dVlp; + Vhp += dVhp; + return (Vlp - Vhp) >> 11; +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/Filter.cpp b/src/sound/resid-fp/Filter.cpp new file mode 100644 index 0000000000..2a2dd24f78 --- /dev/null +++ b/src/sound/resid-fp/Filter.cpp @@ -0,0 +1,90 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2013 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "Filter.h" + +namespace reSIDfp +{ + +void Filter::enable(bool enable) +{ + enabled = enable; + + if (enabled) + { + writeRES_FILT(filt); + } + else + { + filt1 = filt2 = filt3 = filtE = false; + } +} + +void Filter::reset() +{ + writeFC_LO(0); + writeFC_HI(0); + writeMODE_VOL(0); + writeRES_FILT(0); +} + +void Filter::writeFC_LO(unsigned char fc_lo) +{ + fc = (fc & 0x7f8) | (fc_lo & 0x007); + updatedCenterFrequency(); +} + +void Filter::writeFC_HI(unsigned char fc_hi) +{ + fc = (fc_hi << 3 & 0x7f8) | (fc & 0x007); + updatedCenterFrequency(); +} + +void Filter::writeRES_FILT(unsigned char res_filt) +{ + filt = res_filt; + + updateResonance((res_filt >> 4) & 0x0f); + + if (enabled) + { + filt1 = (filt & 0x01) != 0; + filt2 = (filt & 0x02) != 0; + filt3 = (filt & 0x04) != 0; + filtE = (filt & 0x08) != 0; + } + + updatedMixing(); +} + +void Filter::writeMODE_VOL(unsigned char mode_vol) +{ + vol = mode_vol & 0x0f; + lp = (mode_vol & 0x10) != 0; + bp = (mode_vol & 0x20) != 0; + hp = (mode_vol & 0x40) != 0; + voice3off = (mode_vol & 0x80) != 0; + + updatedMixing(); +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/Filter.h b/src/sound/resid-fp/Filter.h new file mode 100644 index 0000000000..4b3473369e --- /dev/null +++ b/src/sound/resid-fp/Filter.h @@ -0,0 +1,177 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2017 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILTER_H +#define FILTER_H + +namespace reSIDfp +{ + +/** + * SID filter base class + */ +class Filter +{ +protected: + /// Current volume amplifier setting. + unsigned short* currentGain; + + /// Current filter/voice mixer setting. + unsigned short* currentMixer; + + /// Filter input summer setting. + unsigned short* currentSummer; + + /// Filter resonance value. + unsigned short* currentResonance; + + /// Filter highpass state. + int Vhp; + + /// Filter bandpass state. + int Vbp; + + /// Filter lowpass state. + int Vlp; + + /// Filter external input. + int ve; + + /// Filter cutoff frequency. + unsigned int fc; + + /// Routing to filter or outside filter + bool filt1, filt2, filt3, filtE; + + /// Switch voice 3 off. + bool voice3off; + + /// Highpass, bandpass, and lowpass filter modes. + bool hp, bp, lp; + + /// Current volume. + unsigned char vol; + +private: + /// Filter enabled. + bool enabled; + + /// Selects which inputs to route through filter. + unsigned char filt; + +protected: + /** + * Set filter cutoff frequency. + */ + virtual void updatedCenterFrequency() = 0; + + /** + * Set filter resonance. + */ + virtual void updateResonance(unsigned char res) = 0; + + /** + * Mixing configuration modified (offsets change) + */ + virtual void updatedMixing() = 0; + +public: + Filter() : + currentGain(nullptr), + currentMixer(nullptr), + currentSummer(nullptr), + currentResonance(nullptr), + Vhp(0), + Vbp(0), + Vlp(0), + ve(0), + fc(0), + filt1(false), + filt2(false), + filt3(false), + filtE(false), + voice3off(false), + hp(false), + bp(false), + lp(false), + vol(0), + enabled(true), + filt(0) {} + + virtual ~Filter() {} + + /** + * SID clocking - 1 cycle + * + * @param v1 voice 1 in + * @param v2 voice 2 in + * @param v3 voice 3 in + * @return filtered output + */ + virtual unsigned short clock(int v1, int v2, int v3) = 0; + + /** + * Enable filter. + * + * @param enable + */ + void enable(bool enable); + + /** + * SID reset. + */ + void reset(); + + /** + * Write Frequency Cutoff Low register. + * + * @param fc_lo Frequency Cutoff Low-Byte + */ + void writeFC_LO(unsigned char fc_lo); + + /** + * Write Frequency Cutoff High register. + * + * @param fc_hi Frequency Cutoff High-Byte + */ + void writeFC_HI(unsigned char fc_hi); + + /** + * Write Resonance/Filter register. + * + * @param res_filt Resonance/Filter + */ + void writeRES_FILT(unsigned char res_filt); + + /** + * Write filter Mode/Volume register. + * + * @param mode_vol Filter Mode/Volume + */ + void writeMODE_VOL(unsigned char mode_vol); + + virtual void input(int input) = 0; +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/Filter6581.cpp b/src/sound/resid-fp/Filter6581.cpp new file mode 100644 index 0000000000..c064a88016 --- /dev/null +++ b/src/sound/resid-fp/Filter6581.cpp @@ -0,0 +1,75 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2015 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define FILTER6581_CPP + +#include "Filter6581.h" + +#include "Integrator6581.h" + +namespace reSIDfp +{ + +Filter6581::~Filter6581() +{ + delete [] f0_dac; +} + +void Filter6581::updatedCenterFrequency() +{ + const unsigned short Vw = f0_dac[fc]; + hpIntegrator->setVw(Vw); + bpIntegrator->setVw(Vw); +} + +void Filter6581::updatedMixing() +{ + currentGain = gain_vol[vol]; + + unsigned int ni = 0; + unsigned int no = 0; + + (filt1 ? ni : no)++; + (filt2 ? ni : no)++; + + if (filt3) ni++; + else if (!voice3off) no++; + + (filtE ? ni : no)++; + + currentSummer = summer[ni]; + + if (lp) no++; + if (bp) no++; + if (hp) no++; + + currentMixer = mixer[no]; +} + +void Filter6581::setFilterCurve(double curvePosition) +{ + delete [] f0_dac; + f0_dac = FilterModelConfig6581::getInstance()->getDAC(curvePosition); + updatedCenterFrequency(); +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/Filter6581.h b/src/sound/resid-fp/Filter6581.h new file mode 100644 index 0000000000..7fca331ab4 --- /dev/null +++ b/src/sound/resid-fp/Filter6581.h @@ -0,0 +1,425 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2022 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILTER6581_H +#define FILTER6581_H + +#include "siddefs-fp.h" + +#include + +#include "Filter.h" +#include "FilterModelConfig6581.h" + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +class Integrator6581; + +/** + * The SID filter is modeled with a two-integrator-loop biquadratic filter, + * which has been confirmed by Bob Yannes to be the actual circuit used in + * the SID chip. + * + * Measurements show that excellent emulation of the SID filter is achieved, + * except when high resonance is combined with high sustain levels. + * In this case the SID op-amps are performing less than ideally and are + * causing some peculiar behavior of the SID filter. This however seems to + * have more effect on the overall amplitude than on the color of the sound. + * + * The theory for the filter circuit can be found in "Microelectric Circuits" + * by Adel S. Sedra and Kenneth C. Smith. + * The circuit is modeled based on the explanation found there except that + * an additional inverter is used in the feedback from the bandpass output, + * allowing the summer op-amp to operate in single-ended mode. This yields + * filter outputs with levels independent of Q, which corresponds with the + * results obtained from a real SID. + * + * We have been able to model the summer and the two integrators of the circuit + * to form components of an IIR filter. + * Vhp is the output of the summer, Vbp is the output of the first integrator, + * and Vlp is the output of the second integrator in the filter circuit. + * + * According to Bob Yannes, the active stages of the SID filter are not really + * op-amps. Rather, simple NMOS inverters are used. By biasing an inverter + * into its region of quasi-linear operation using a feedback resistor from + * input to output, a MOS inverter can be made to act like an op-amp for + * small signals centered around the switching threshold. + * + * In 2008, Michael Huth facilitated closer investigation of the SID 6581 + * filter circuit by publishing high quality microscope photographs of the die. + * Tommi Lempinen has done an impressive work on re-vectorizing and annotating + * the die photographs, substantially simplifying further analysis of the + * filter circuit. + * + * The filter schematics below are reverse engineered from these re-vectorized + * and annotated die photographs. While the filter first depicted in reSID 0.9 + * is a correct model of the basic filter, the schematics are now completed + * with the audio mixer and output stage, including details on intended + * relative resistor values. Also included are schematics for the NMOS FET + * voltage controlled resistors (VCRs) used to control cutoff frequency, the + * DAC which controls the VCRs, the NMOS op-amps, and the output buffer. + * + * + * SID filter / mixer / output + * --------------------------- + * ~~~ + * +---------------------------------------------------+ + * | | + * | +--1R1-- \--+ D7 | + * | +---R1--+ | | | + * | | | o--2R1-- \--o D6 | + * | +---------o----o--Rw--o--[A>--o--Rw--o--[A>--o + * ve (EXT IN) | | | | + * D3 \ ---------------R8--o | | (CAP2A) | (CAP1A) + * | v3 | | vhp | vbp | vlp + * D2 | \ -----------R8--o +-----+ | | + * | | v2 | | | | + * D1 | | \ -------R8--o | +----------------+ | + * | | | v1 | | | | + * D0 | | | \ ---R8--+ | | +---------------------------+ + * | | | | | | | + * R6 R6 R6 R6 R6 R6 R6 + * | | | | $18 | | | $18 + * | \ | | D7: 1=open \ \ \ D6 - D4: 0=open + * | | | | | | | + * +---o---o---o-------------o---o---+ 12V + * | + * | D3 +--/ --1R2--+ | + * | +---R8--+ | | +---R2--+ | + * | | | D2 o--/ --2R2--o | | ||--+ + * +---o--[A>--o------o o--o--[A>--o--|| + * D1 o--/ --4R2--o (4.25R2) ||--+ + * $18 | | | + * 0=open D0 +--/ --8R2--+ (8.75R2) | + * + * vo (AUDIO + * OUT) + * + * + * v1 - voice 1 + * v2 - voice 2 + * v3 - voice 3 + * ve - ext in + * vhp - highpass output + * vbp - bandpass output + * vlp - lowpass output + * vo - audio out + * [A> - single ended inverting op-amp (self-biased NMOS inverter) + * Rn - "resistors", implemented with custom NMOS FETs + * Rw - cutoff frequency resistor (VCR) + * C - capacitor + * ~~~ + * Notes: + * + * R2 ~ 2.0*R1 + * R6 ~ 6.0*R1 + * R8 ~ 8.0*R1 + * R24 ~ 24.0*R1 + * + * The Rn "resistors" in the circuit are implemented with custom NMOS FETs, + * probably because of space constraints on the SID die. The silicon substrate + * is laid out in a narrow strip or "snake", with a strip length proportional + * to the intended resistance. The polysilicon gate electrode covers the entire + * silicon substrate and is fixed at 12V in order for the NMOS FET to operate + * in triode mode (a.k.a. linear mode or ohmic mode). + * + * Even in "linear mode", an NMOS FET is only an approximation of a resistor, + * as the apparant resistance increases with increasing drain-to-source + * voltage. If the drain-to-source voltage should approach the gate voltage + * of 12V, the NMOS FET will enter saturation mode (a.k.a. active mode), and + * the NMOS FET will not operate anywhere like a resistor. + * + * + * + * NMOS FET voltage controlled resistor (VCR) + * ------------------------------------------ + * ~~~ + * Vw + * + * | + * | + * R1 + * | + * +--R1--o + * | __|__ + * | ----- + * | | | + * vi -----o----+ +--o----- vo + * | | + * +----R24----+ + * + * + * vi - input + * vo - output + * Rn - "resistors", implemented with custom NMOS FETs + * Vw - voltage from 11-bit DAC (frequency cutoff control) + * ~~~ + * Notes: + * + * An approximate value for R24 can be found by using the formula for the + * filter cutoff frequency: + * + * FCmin = 1/(2*pi*Rmax*C) + * + * Assuming that a the setting for minimum cutoff frequency in combination with + * a low level input signal ensures that only negligible current will flow + * through the transistor in the schematics above, values for FCmin and C can + * be substituted in this formula to find Rmax. + * Using C = 470pF and FCmin = 220Hz (measured value), we get: + * + * FCmin = 1/(2*pi*Rmax*C) + * Rmax = 1/(2*pi*FCmin*C) = 1/(2*pi*220*470e-12) ~ 1.5MOhm + * + * From this it follows that: + * R24 = Rmax ~ 1.5MOhm + * R1 ~ R24/24 ~ 64kOhm + * R2 ~ 2.0*R1 ~ 128kOhm + * R6 ~ 6.0*R1 ~ 384kOhm + * R8 ~ 8.0*R1 ~ 512kOhm + * + * Note that these are only approximate values for one particular SID chip, + * due to process variations the values can be substantially different in + * other chips. + * + * + * + * Filter frequency cutoff DAC + * --------------------------- + * + * ~~~ + * 12V 10 9 8 7 6 5 4 3 2 1 0 VGND + * | | | | | | | | | | | | | Missing + * 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R 2R termination + * | | | | | | | | | | | | | + * Vw --o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o-R-o- -+ + * + * + * Bit on: 12V + * Bit off: 5V (VGND) + * ~~~ + * As is the case with all MOS 6581 DACs, the termination to (virtual) ground + * at bit 0 is missing. + * + * Furthermore, the control of the two VCRs imposes a load on the DAC output + * which varies with the input signals to the VCRs. This can be seen from the + * VCR figure above. + * + * + * + * "Op-amp" (self-biased NMOS inverter) + * ------------------------------------ + * ~~~ + * + * 12V + * + * | + * +-----------o + * | | + * | +------o + * | | | + * | | ||--+ + * | +--|| + * | ||--+ + * ||--+ | + * vi -----|| o---o----- vo + * ||--+ | | + * | ||--+ | + * |-------|| | + * | ||--+ | + * ||--+ | | + * +--|| | | + * | ||--+ | | + * | | | | + * | +-----------o | + * | | | + * | | + * | GND | + * | | + * +----------------------+ + * + * + * vi - input + * vo - output + * ~~~ + * Notes: + * + * The schematics above are laid out to show that the "op-amp" logically + * consists of two building blocks; a saturated load NMOS inverter (on the + * right hand side of the schematics) with a buffer / bias input stage + * consisting of a variable saturated load NMOS inverter (on the left hand + * side of the schematics). + * + * Provided a reasonably high input impedance and a reasonably low output + * impedance, the "op-amp" can be modeled as a voltage transfer function + * mapping input voltage to output voltage. + * + * + * + * Output buffer (NMOS voltage follower) + * ------------------------------------- + * ~~~ + * + * 12V + * + * | + * | + * ||--+ + * vi -----|| + * ||--+ + * | + * o------ vo + * | (AUDIO + * Rext OUT) + * | + * | + * + * GND + * + * vi - input + * vo - output + * Rext - external resistor, 1kOhm + * ~~~ + * Notes: + * + * The external resistor Rext is needed to complete the NMOS voltage follower, + * this resistor has a recommended value of 1kOhm. + * + * Die photographs show that actually, two NMOS transistors are used in the + * voltage follower. However the two transistors are coupled in parallel (all + * terminals are pairwise common), which implies that we can model the two + * transistors as one. + */ +class Filter6581 final : public Filter +{ +private: + const unsigned short* f0_dac; + + unsigned short** mixer; + unsigned short** summer; + unsigned short** gain_res; + unsigned short** gain_vol; + + const int voiceScaleS11; + const int voiceDC; + + /// VCR + associated capacitor connected to highpass output. + std::unique_ptr const hpIntegrator; + + /// VCR + associated capacitor connected to bandpass output. + std::unique_ptr const bpIntegrator; + +protected: + /** + * Set filter cutoff frequency. + */ + void updatedCenterFrequency() override; + + /** + * Set filter resonance. + * + * In the MOS 6581, 1/Q is controlled linearly by res. + */ + void updateResonance(unsigned char res) override { currentResonance = gain_res[res]; } + + void updatedMixing() override; + +public: + Filter6581() : + f0_dac(FilterModelConfig6581::getInstance()->getDAC(0.5)), + mixer(FilterModelConfig6581::getInstance()->getMixer()), + summer(FilterModelConfig6581::getInstance()->getSummer()), + gain_res(FilterModelConfig6581::getInstance()->getGainRes()), + gain_vol(FilterModelConfig6581::getInstance()->getGainVol()), + voiceScaleS11(FilterModelConfig6581::getInstance()->getVoiceScaleS11()), + voiceDC(FilterModelConfig6581::getInstance()->getNormalizedVoiceDC()), + hpIntegrator(FilterModelConfig6581::getInstance()->buildIntegrator()), + bpIntegrator(FilterModelConfig6581::getInstance()->buildIntegrator()) + { + input(0); + } + + ~Filter6581(); + + unsigned short clock(int voice1, int voice2, int voice3) override; + + void input(int sample) override { ve = (sample * voiceScaleS11 * 3 >> 11) + mixer[0][0]; } + + /** + * Set filter curve type based on single parameter. + * + * @param curvePosition 0 .. 1, where 0 sets center frequency high ("light") and 1 sets it low ("dark"), default is 0.5 + */ + void setFilterCurve(double curvePosition); +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(FILTER6581_CPP) + +#include "Integrator6581.h" + +namespace reSIDfp +{ + +RESID_INLINE +unsigned short Filter6581::clock(int voice1, int voice2, int voice3) +{ + voice1 = (voice1 * voiceScaleS11 >> 15) + voiceDC; + voice2 = (voice2 * voiceScaleS11 >> 15) + voiceDC; + // Voice 3 is silenced by voice3off if it is not routed through the filter. + voice3 = (filt3 || !voice3off) ? (voice3 * voiceScaleS11 >> 15) + voiceDC : 0; + + int Vi = 0; + int Vo = 0; + + (filt1 ? Vi : Vo) += voice1; + (filt2 ? Vi : Vo) += voice2; + (filt3 ? Vi : Vo) += voice3; + (filtE ? Vi : Vo) += ve; + + Vhp = currentSummer[currentResonance[Vbp] + Vlp + Vi]; + Vbp = hpIntegrator->solve(Vhp); + Vlp = bpIntegrator->solve(Vbp); + + if (lp) Vo += Vlp; + if (bp) Vo += Vbp; + if (hp) Vo += Vhp; + + return currentGain[currentMixer[Vo]]; +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/Filter8580.cpp b/src/sound/resid-fp/Filter8580.cpp new file mode 100644 index 0000000000..a70285a8a0 --- /dev/null +++ b/src/sound/resid-fp/Filter8580.cpp @@ -0,0 +1,101 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2019 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define FILTER8580_CPP + +#include "Filter8580.h" + +#include "Integrator8580.h" + +namespace reSIDfp +{ + +/** + * W/L ratio of frequency DAC bit 0, + * other bit are proportional. + * When no bit are selected a resistance with half + * W/L ratio is selected. + */ +const double DAC_WL0 = 0.00615; + +Filter8580::~Filter8580() {} + +void Filter8580::updatedCenterFrequency() +{ + double wl; + double dacWL = DAC_WL0; + if (fc) + { + wl = 0.; + for (unsigned int i = 0; i < 11; i++) + { + if (fc & (1 << i)) + { + wl += dacWL; + } + dacWL *= 2.; + } + } + else + { + wl = dacWL/2.; + } + + hpIntegrator->setFc(wl); + bpIntegrator->setFc(wl); +} + +void Filter8580::updatedMixing() +{ + currentGain = gain_vol[vol]; + + unsigned int ni = 0; + unsigned int no = 0; + + (filt1 ? ni : no)++; + (filt2 ? ni : no)++; + + if (filt3) ni++; + else if (!voice3off) no++; + + (filtE ? ni : no)++; + + currentSummer = summer[ni]; + + if (lp) no++; + if (bp) no++; + if (hp) no++; + + currentMixer = mixer[no]; +} + +void Filter8580::setFilterCurve(double curvePosition) +{ + // Adjust cp + // 1.2 <= cp <= 1.8 + cp = 1.8 - curvePosition * 3./5.; + + hpIntegrator->setV(cp); + bpIntegrator->setV(cp); +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/Filter8580.h b/src/sound/resid-fp/Filter8580.h new file mode 100644 index 0000000000..2166ec0da6 --- /dev/null +++ b/src/sound/resid-fp/Filter8580.h @@ -0,0 +1,383 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2022 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILTER8580_H +#define FILTER8580_H + +#include "siddefs-fp.h" + +#include + +#include "Filter.h" +#include "FilterModelConfig8580.h" +#include "Integrator8580.h" + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +class Integrator8580; + +/** + * Filter for 8580 chip + * -------------------- + * The 8580 filter stage had been redesigned to be more linear and robust + * against temperature change. It also features real op-amps and a + * revisited resonance model. + * The filter schematics below are reverse engineered from re-vectorized + * and annotated die photographs. Credits to Michael Huth for the microscope + * photographs of the die, Tommi Lempinen for re-vectorizating and annotating + * the images and ttlworks from forum.6502.org for the circuit analysis. + * + * ~~~ + * + * +---------------------------------------------------+ + * | $17 +----Rf-+ | + * | | | | + * | D4&!D5 o- \-R3-o | + * | | | $17 | + * | !D4&!D5 o- \-R2-o | + * | | | +---R8-- \--+ !D6&D7 | + * | D4&!D5 o- \-R1-o | | | + * | | | o---RC-- \--o D6&D7 | + * | +---------o----o--Rfc-o--[A>--o--Rfc-o--[A>--o + * ve (EXT IN) | | | | + * D3 \ --------------R12--o | | (CAP2A) | (CAP1A) + * | v3 | | vhp | vbp | vlp + * D2 | \ -----------R7--o +-----+ | | + * | | v2 | | | | + * D1 | | \ -------R7--o | +----------------+ | + * | | | v1 | | | | + * D0 | | | \ ---R7--+ | | +---------------------------+ + * | | | | | | | + * R9 R5 R5 R5 R5 R5 R5 + * | | | | $18 | | | $18 + * | \ | | D7: 1=open \ \ \ D6 - D4: 0=open + * | | | | | | | + * +---o---o---o-------------o---o---+ + * | + * | D3 +--/ --1R4--+ + * | +---R8--+ | | +---R2--+ + * | | | D2 o--/ --2R4--o | | + * +---o--[A>--o------o o--o--[A>--o-- vo (AUDIO OUT) + * D1 o--/ --4R4--o + * $18 | | + * 0=open D0 +--/ --8R4--+ + * + * + * + * Resonance + * --------- + * For resonance, we have two tiny DACs that controls both the input + * and feedback resistances. + * + * The "resistors" are switched in as follows by bits in register $17: + * + * feedback: + * R1: bit4&!bit5 + * R2: !bit4&bit5 + * R3: bit4&bit5 + * Rf: always on + * + * input: + * R4: bit6&!bit7 + * R8: !bit6&bit7 + * RC: bit6&bit7 + * Ri: !(R4|R8|RC) = !(bit6|bit7) = !bit6&!bit7 + * + * + * The relative "resistor" values are approximately (using channel length): + * + * R1 = 15.3*Ri + * R2 = 7.3*Ri + * R3 = 4.7*Ri + * Rf = 1.4*Ri + * R4 = 1.4*Ri + * R8 = 2.0*Ri + * RC = 2.8*Ri + * + * + * Approximate values for 1/Q can now be found as follows (assuming an + * ideal op-amp): + * + * res feedback input -gain (1/Q) + * --- -------- ----- ---------- + * 0 Rf Ri Rf/Ri = 1/(Ri*(1/Rf)) = 1/0.71 + * 1 Rf|R1 Ri (Rf|R1)/Ri = 1/(Ri*(1/Rf+1/R1)) = 1/0.78 + * 2 Rf|R2 Ri (Rf|R2)/Ri = 1/(Ri*(1/Rf+1/R2)) = 1/0.85 + * 3 Rf|R3 Ri (Rf|R3)/Ri = 1/(Ri*(1/Rf+1/R3)) = 1/0.92 + * 4 Rf R4 Rf/R4 = 1/(R4*(1/Rf)) = 1/1.00 + * 5 Rf|R1 R4 (Rf|R1)/R4 = 1/(R4*(1/Rf+1/R1)) = 1/1.10 + * 6 Rf|R2 R4 (Rf|R2)/R4 = 1/(R4*(1/Rf+1/R2)) = 1/1.20 + * 7 Rf|R3 R4 (Rf|R3)/R4 = 1/(R4*(1/Rf+1/R3)) = 1/1.30 + * 8 Rf R8 Rf/R8 = 1/(R8*(1/Rf)) = 1/1.43 + * 9 Rf|R1 R8 (Rf|R1)/R8 = 1/(R8*(1/Rf+1/R1)) = 1/1.56 + * A Rf|R2 R8 (Rf|R2)/R8 = 1/(R8*(1/Rf+1/R2)) = 1/1.70 + * B Rf|R3 R8 (Rf|R3)/R8 = 1/(R8*(1/Rf+1/R3)) = 1/1.86 + * C Rf RC Rf/RC = 1/(RC*(1/Rf)) = 1/2.00 + * D Rf|R1 RC (Rf|R1)/RC = 1/(RC*(1/Rf+1/R1)) = 1/2.18 + * E Rf|R2 RC (Rf|R2)/RC = 1/(RC*(1/Rf+1/R2)) = 1/2.38 + * F Rf|R3 RC (Rf|R3)/RC = 1/(RC*(1/Rf+1/R3)) = 1/2.60 + * + * + * These data indicate that the following function for 1/Q has been + * modeled in the MOS 8580: + * + * 1/Q = 2^(1/2)*2^(-x/8) = 2^(1/2 - x/8) = 2^((4 - x)/8) + * + * + * + * Op-amps + * ------- + * Unlike the 6581, the 8580 has real OpAmps. + * + * Temperature compensated differential amplifier: + * + * 9V + * + * | + * +-------o-o-o-------+ + * | | | | + * | R R | + * +--|| | | ||--+ + * ||---o o---|| + * +--|| | | ||--+ + * | | | | + * o-----+ | | o--- Va + * | | | | | + * +--|| | | | ||--+ + * ||-o-+---+---|| + * +--|| | | ||--+ + * | | | | + * | | + * GND | | GND + * ||--+ +--|| + * in- -----|| ||------ in+ + * ||----o----|| + * | + * 8 Current sink + * | + * + * GND + * + * Inverter + non-inverting output amplifier: + * + * Va ---o---||-------------------o--------------------+ + * | | 9V | + * | +----------+----------+ | | + * | 9V | | 9V | ||--+ | + * | | | 9V | | +-|| | + * | R | | | ||--+ ||--+ | + * | | | ||--+ +--|| o---o--- Vout + * | o---o---|| ||--+ ||--+ + * | | ||--+ o-----|| + * | ||--+ | ||--+ ||--+ + * +-----|| o-----|| | + * ||--+ | ||--+ + * | R | GND + * | + * GND GND + * GND + * + * + * + * Virtual ground + * -------------- + * A PolySi resitive voltage divider provides the voltage + * for the positive input of the filter op-amps. + * + * 5V + * +----------+ + * | | |\ | + * R1 +---|-\ | + * 5V | |A >---o--- Vref + * o-------|+/ + * | | |/ + * R10 R4 + * | | + * o---+ + * | + * R10 + * | + * + * GND + * + * Rn = n*R1 + * + * + * + * Rfc - freq control DAC resistance ladder + * ---------------------------------------- + * The 8580 has 11 bits for frequency control, but 12 bit DACs. + * If those 11 bits would be '0', the impedance of the DACs would be "infinitely high". + * To get around this, there is an 11 input NOR gate below the DACs sensing those 11 bits. + * If all are 0, the NOR gate gives the gate control voltage to the 12 bit DAC LSB. + * + * ----o---o--...--o---o---o--- + * | | | | | + * Rb10 Rb9 ... Rb1 Rb0 R0 + * | | | | | + * ----o---o--...--o---o---o--- + * + * + * + * Crystal stabilized precision switched capacitor voltage divider + * --------------------------------------------------------------- + * There is a FET working as a temperature sensor close to the DACs which changes the gate voltage + * of the frequency control DACs according to the temperature of the DACs, + * to reduce the effects of temperature on the filter curve. + * An asynchronous 3 bit binary counter, running at the speed of PHI2, drives two big capacitors + * whose AC resistance is then used as a voltage divider. + * This implicates that frequency difference between PAL and NTSC might shift the filter curve by 4% or such. + * + * |\ OpAmp has a smaller capacitor than the other OPs + * Vref ---|+\ + * |A >---o--- Vdac + * +-------|-/ | + * | |/ | + * | | + * C1 | C2 | + * +---||---o---+ +---o-----||-------o + * | | | | | | + * o----+ | ----- | | + * | | | ----- +----+ +-----o + * | ----- | | | | + * | ----- | ----- | + * | | | ----- | + * | +-----------+ | | + * | /Q Q | +-------+ + * GND +-----------+ FET close to DAC + * | clk/8 | working as temperature sensor + * +-----------+ + */ +class Filter8580 final : public Filter +{ +private: + unsigned short** mixer; + unsigned short** summer; + unsigned short** gain_res; + unsigned short** gain_vol; + + const int voiceScaleS11; + const int voiceDC; + + double cp; + + /// VCR + associated capacitor connected to highpass output. + std::unique_ptr const hpIntegrator; + + /// VCR + associated capacitor connected to bandpass output. + std::unique_ptr const bpIntegrator; + +protected: + /** + * Set filter cutoff frequency. + */ + void updatedCenterFrequency() override; + + /** + * Set filter resonance. + * + * @param res the new resonance value + */ + void updateResonance(unsigned char res) override { currentResonance = gain_res[res]; } + + void updatedMixing() override; + +public: + Filter8580() : + mixer(FilterModelConfig8580::getInstance()->getMixer()), + summer(FilterModelConfig8580::getInstance()->getSummer()), + gain_res(FilterModelConfig8580::getInstance()->getGainRes()), + gain_vol(FilterModelConfig8580::getInstance()->getGainVol()), + voiceScaleS11(FilterModelConfig8580::getInstance()->getVoiceScaleS11()), + voiceDC(FilterModelConfig8580::getInstance()->getNormalizedVoiceDC()), + cp(0.5), + hpIntegrator(FilterModelConfig8580::getInstance()->buildIntegrator()), + bpIntegrator(FilterModelConfig8580::getInstance()->buildIntegrator()) + { + setFilterCurve(cp); + input(0); + } + + ~Filter8580(); + + unsigned short clock(int voice1, int voice2, int voice3) override; + + void input(int sample) override { ve = (sample * voiceScaleS11 * 3 >> 11) + mixer[0][0]; } + + /** + * Set filter curve type based on single parameter. + * + * @param curvePosition 0 .. 1, where 0 sets center frequency high ("light") and 1 sets it low ("dark"), default is 0.5 + */ + void setFilterCurve(double curvePosition); +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(FILTER8580_CPP) + +namespace reSIDfp +{ + +RESID_INLINE +unsigned short Filter8580::clock(int voice1, int voice2, int voice3) +{ + voice1 = (voice1 * voiceScaleS11 >> 15) + voiceDC; + voice2 = (voice2 * voiceScaleS11 >> 15) + voiceDC; + // Voice 3 is silenced by voice3off if it is not routed through the filter. + voice3 = (filt3 || !voice3off) ? (voice3 * voiceScaleS11 >> 15) + voiceDC : 0; + + int Vi = 0; + int Vo = 0; + + (filt1 ? Vi : Vo) += voice1; + (filt2 ? Vi : Vo) += voice2; + (filt3 ? Vi : Vo) += voice3; + (filtE ? Vi : Vo) += ve; + + Vhp = currentSummer[currentResonance[Vbp] + Vlp + Vi]; + Vbp = hpIntegrator->solve(Vhp); + Vlp = bpIntegrator->solve(Vbp); + + if (lp) Vo += Vlp; + if (bp) Vo += Vbp; + if (hp) Vo += Vhp; + + return currentGain[currentMixer[Vo]]; +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/FilterModelConfig.cpp b/src/sound/resid-fp/FilterModelConfig.cpp new file mode 100644 index 0000000000..cd4b204000 --- /dev/null +++ b/src/sound/resid-fp/FilterModelConfig.cpp @@ -0,0 +1,82 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2022 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "FilterModelConfig.h" + +#include + +namespace reSIDfp +{ + +FilterModelConfig::FilterModelConfig( + double vvr, + double vdv, + double c, + double vdd, + double vth, + double ucox, + const Spline::Point *opamp_voltage, + int opamp_size +) : + voice_voltage_range(vvr), + voice_DC_voltage(vdv), + C(c), + Vdd(vdd), + Vth(vth), + Ut(26.0e-3), + uCox(ucox), + Vddt(Vdd - Vth), + vmin(opamp_voltage[0].x), + vmax(std::max(Vddt, opamp_voltage[0].y)), + denorm(vmax - vmin), + norm(1.0 / denorm), + N16(norm * ((1 << 16) - 1)), + currFactorCoeff(denorm * (uCox / 2. * 1.0e-6 / C)) +{ + // Convert op-amp voltage transfer to 16 bit values. + + std::vector scaled_voltage(opamp_size); + + for (int i = 0; i < opamp_size; i++) + { + scaled_voltage[i].x = N16 * (opamp_voltage[i].x - opamp_voltage[i].y) / 2.; + // We add 32768 to get a positive number in the range [0-65535] + scaled_voltage[i].x += static_cast(1u << 15); + + scaled_voltage[i].y = N16 * (opamp_voltage[i].x - vmin); + } + + // Create lookup table mapping capacitor voltage to op-amp input voltage: + + Spline s(scaled_voltage); + + for (int x = 0; x < (1 << 16); x++) + { + const Spline::Point out = s.evaluate(x); + // When interpolating outside range the first elements may be negative + double tmp = out.x > 0. ? out.x : 0.; + assert(tmp < 65535.5); + opamp_rev[x] = static_cast(tmp + 0.5); + } +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/FilterModelConfig.h b/src/sound/resid-fp/FilterModelConfig.h new file mode 100644 index 0000000000..9e557d363a --- /dev/null +++ b/src/sound/resid-fp/FilterModelConfig.h @@ -0,0 +1,165 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILTERMODELCONFIG_H +#define FILTERMODELCONFIG_H + +#include +#include + +#include "Spline.h" + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +class FilterModelConfig +{ +protected: + const double voice_voltage_range; + const double voice_DC_voltage; + + /// Capacitor value. + const double C; + + /// Transistor parameters. + //@{ + const double Vdd; + const double Vth; ///< Threshold voltage + const double Ut; ///< Thermal voltage: Ut = kT/q = 8.61734315e-5*T ~ 26mV + const double uCox; ///< Transconductance coefficient: u*Cox + const double Vddt; ///< Vdd - Vth + //@} + + // Derived stuff + const double vmin, vmax; + const double denorm, norm; + + /// Fixed point scaling for 16 bit op-amp output. + const double N16; + + /// Current factor coefficient for op-amp integrators. + const double currFactorCoeff; + + /// Lookup tables for gain and summer op-amps in output stage / filter. + //@{ + unsigned short* mixer[8]; //-V730_NOINIT this is initialized in the derived class constructor + unsigned short* summer[5]; //-V730_NOINIT this is initialized in the derived class constructor + unsigned short* gain_vol[16]; //-V730_NOINIT this is initialized in the derived class constructor + unsigned short* gain_res[16]; //-V730_NOINIT this is initialized in the derived class constructor + //@} + + /// Reverse op-amp transfer function. + unsigned short opamp_rev[1 << 16]; //-V730_NOINIT this is initialized in the derived class constructor + +private: + FilterModelConfig (const FilterModelConfig&) DELETE; + FilterModelConfig& operator= (const FilterModelConfig&) DELETE; + +protected: + /** + * @param vvr voice voltage range + * @param vdv voice DC voltage + * @param c capacitor value + * @param vdd Vdd + * @param vth threshold voltage + * @param ucox u*Cox + * @param ominv opamp min voltage + * @param omaxv opamp max voltage + */ + FilterModelConfig( + double vvr, + double vdv, + double c, + double vdd, + double vth, + double ucox, + const Spline::Point *opamp_voltage, + int opamp_size + ); + + ~FilterModelConfig() + { + for (int i = 0; i < 8; i++) + { + delete [] mixer[i]; + } + + for (int i = 0; i < 5; i++) + { + delete [] summer[i]; + } + + for (int i = 0; i < 16; i++) + { + delete [] gain_vol[i]; + delete [] gain_res[i]; + } + } + +public: + unsigned short** getGainVol() { return gain_vol; } + unsigned short** getGainRes() { return gain_res; } + unsigned short** getSummer() { return summer; } + unsigned short** getMixer() { return mixer; } + + /** + * The digital range of one voice is 20 bits; create a scaling term + * for multiplication which fits in 11 bits. + */ + int getVoiceScaleS11() const { return static_cast((norm * ((1 << 11) - 1)) * voice_voltage_range); } + + /** + * The "zero" output level of the voices. + */ + int getNormalizedVoiceDC() const { return static_cast(N16 * (voice_DC_voltage - vmin)); } + + inline unsigned short getOpampRev(int i) const { return opamp_rev[i]; } + inline double getVddt() const { return Vddt; } + inline double getVth() const { return Vth; } + + // helper functions + inline unsigned short getNormalizedValue(double value) const + { + const double tmp = N16 * (value - vmin); + assert(tmp > -0.5 && tmp < 65535.5); + return static_cast(tmp + 0.5); + } + + inline unsigned short getNormalizedCurrentFactor(double wl) const + { + const double tmp = (1 << 13) * currFactorCoeff * wl; + assert(tmp > -0.5 && tmp < 65535.5); + return static_cast(tmp + 0.5); + } + + inline unsigned short getNVmin() const { + const double tmp = N16 * vmin; + assert(tmp > -0.5 && tmp < 65535.5); + return static_cast(tmp + 0.5); + } +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/FilterModelConfig6581.cpp b/src/sound/resid-fp/FilterModelConfig6581.cpp new file mode 100644 index 0000000000..143b9e91c1 --- /dev/null +++ b/src/sound/resid-fp/FilterModelConfig6581.cpp @@ -0,0 +1,328 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "FilterModelConfig6581.h" + +#include + +#include "Integrator6581.h" +#include "OpAmp.h" + +namespace reSIDfp +{ + +#ifndef HAVE_CXX11 +/** + * Compute log(1+x) without losing precision for small values of x + * + * @note when compiling with -ffastm-math the compiler will + * optimize the expression away leaving a plain log(1. + x) + */ +inline double log1p(double x) +{ + return log(1. + x) - (((1. + x) - 1.) - x) / (1. + x); +} +#endif + +const unsigned int OPAMP_SIZE = 33; + +/** + * This is the SID 6581 op-amp voltage transfer function, measured on + * CAP1B/CAP1A on a chip marked MOS 6581R4AR 0687 14. + * All measured chips have op-amps with output voltages (and thus input + * voltages) within the range of 0.81V - 10.31V. + */ +const Spline::Point opamp_voltage[OPAMP_SIZE] = +{ + { 0.81, 10.31 }, // Approximate start of actual range + { 2.40, 10.31 }, + { 2.60, 10.30 }, + { 2.70, 10.29 }, + { 2.80, 10.26 }, + { 2.90, 10.17 }, + { 3.00, 10.04 }, + { 3.10, 9.83 }, + { 3.20, 9.58 }, + { 3.30, 9.32 }, + { 3.50, 8.69 }, + { 3.70, 8.00 }, + { 4.00, 6.89 }, + { 4.40, 5.21 }, + { 4.54, 4.54 }, // Working point (vi = vo) + { 4.60, 4.19 }, + { 4.80, 3.00 }, + { 4.90, 2.30 }, // Change of curvature + { 4.95, 2.03 }, + { 5.00, 1.88 }, + { 5.05, 1.77 }, + { 5.10, 1.69 }, + { 5.20, 1.58 }, + { 5.40, 1.44 }, + { 5.60, 1.33 }, + { 5.80, 1.26 }, + { 6.00, 1.21 }, + { 6.40, 1.12 }, + { 7.00, 1.02 }, + { 7.50, 0.97 }, + { 8.50, 0.89 }, + { 10.00, 0.81 }, + { 10.31, 0.81 }, // Approximate end of actual range +}; + +std::unique_ptr FilterModelConfig6581::instance(nullptr); + +FilterModelConfig6581* FilterModelConfig6581::getInstance() +{ + if (!instance.get()) + { + instance.reset(new FilterModelConfig6581()); + } + + return instance.get(); +} + +FilterModelConfig6581::FilterModelConfig6581() : + FilterModelConfig( + 1.5, // voice voltage range + 5.075, // voice DC voltage + 470e-12, // capacitor value + 12.18, // Vdd + 1.31, // Vth + 20e-6, // uCox + opamp_voltage, + OPAMP_SIZE + ), + WL_vcr(9.0 / 1.0), + WL_snake(1.0 / 115.0), + dac_zero(6.65), + dac_scale(2.63), + dac(DAC_BITS) +{ + dac.kinkedDac(MOS6581); + + // Create lookup tables for gains / summers. + +#ifndef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + +// #pragma omp parallel sections + { +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // The filter summer operates at n ~ 1, and has 5 fundamentally different + // input configurations (2 - 6 input "resistors"). + // + // Note that all "on" transistors are modeled as one. This is not + // entirely accurate, since the input for each transistor is different, + // and transistors are not linear components. However modeling all + // transistors separately would be extremely costly. + for (int i = 0; i < 5; i++) + { + const int idiv = 2 + i; // 2 - 6 input "resistors". + const int size = idiv << 16; + const double n = idiv; + opampModel.reset(); + summer[i] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16 / idiv; /* vmin .. vmax */ + summer[i][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // The audio mixer operates at n ~ 8/6, and has 8 fundamentally different + // input configurations (0 - 7 input "resistors"). + // + // All "on", transistors are modeled as one - see comments above for + // the filter summer. + for (int i = 0; i < 8; i++) + { + const int idiv = (i == 0) ? 1 : i; + const int size = (i == 0) ? 1 : i << 16; + const double n = i * 8.0 / 6.0; + opampModel.reset(); + mixer[i] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16 / idiv; /* vmin .. vmax */ + mixer[i][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // 4 bit "resistor" ladders in the audio output gain + // necessitate 16 gain tables. + // From die photographs of the volume "resistor" ladders + // it follows that gain ~ vol/12 (assuming ideal + // op-amps and ideal "resistors"). + for (int n8 = 0; n8 < 16; n8++) + { + const int size = 1 << 16; + const double n = n8 / 12.0; + opampModel.reset(); + gain_vol[n8] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16; /* vmin .. vmax */ + gain_vol[n8][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // 4 bit "resistor" ladders in the bandpass resonance gain + // necessitate 16 gain tables. + // From die photographs of the bandpass "resistor" ladders + // it follows that 1/Q ~ ~res/8 (assuming ideal + // op-amps and ideal "resistors"). + for (int n8 = 0; n8 < 16; n8++) + { + const int size = 1 << 16; + const double n = (~n8 & 0xf) / 8.0; + opampModel.reset(); + gain_res[n8] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16; /* vmin .. vmax */ + gain_res[n8][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { + const double nVddt = N16 * (Vddt - vmin); + + for (unsigned int i = 0; i < (1 << 16); i++) + { + // The table index is right-shifted 16 times in order to fit in + // 16 bits; the argument to sqrt is thus multiplied by (1 << 16). + const double tmp = nVddt - sqrt(static_cast(i << 16)); + assert(tmp > -0.5 && tmp < 65535.5); + vcr_nVg[i] = static_cast(tmp + 0.5); + } + } + +// #pragma omp section + { + // EKV model: + // + // Ids = Is * (if - ir) + // Is = (2 * u*Cox * Ut^2)/k * W/L + // if = ln^2(1 + e^((k*(Vg - Vt) - Vs)/(2*Ut)) + // ir = ln^2(1 + e^((k*(Vg - Vt) - Vd)/(2*Ut)) + + // moderate inversion characteristic current + const double Is = (2. * uCox * Ut * Ut) * WL_vcr; + + // Normalized current factor for 1 cycle at 1MHz. + const double N15 = norm * ((1 << 15) - 1); + const double n_Is = N15 * 1.0e-6 / C * Is; + + // kVgt_Vx = k*(Vg - Vt) - Vx + // I.e. if k != 1.0, Vg must be scaled accordingly. + for (int kVgt_Vx = 0; kVgt_Vx < (1 << 16); kVgt_Vx++) + { + const double log_term = log1p(exp((kVgt_Vx / N16) / (2. * Ut))); + // Scaled by m*2^15 + const double tmp = n_Is * log_term * log_term; + assert(tmp > -0.5 && tmp < 65535.5); + vcr_n_Ids_term[kVgt_Vx] = static_cast(tmp + 0.5); + } + } + } +} + +unsigned short* FilterModelConfig6581::getDAC(double adjustment) const +{ + const double dac_zero = getDacZero(adjustment); + + unsigned short* f0_dac = new unsigned short[1 << DAC_BITS]; + + for (unsigned int i = 0; i < (1 << DAC_BITS); i++) + { + const double fcd = dac.getOutput(i); + f0_dac[i] = getNormalizedValue(dac_zero + fcd * dac_scale / (1 << DAC_BITS)); + } + + return f0_dac; +} + +std::unique_ptr FilterModelConfig6581::buildIntegrator() +{ + return MAKE_UNIQUE(Integrator6581, this, WL_snake); +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/FilterModelConfig6581.h b/src/sound/resid-fp/FilterModelConfig6581.h new file mode 100644 index 0000000000..06fcc5ce8e --- /dev/null +++ b/src/sound/resid-fp/FilterModelConfig6581.h @@ -0,0 +1,112 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILTERMODELCONFIG6581_H +#define FILTERMODELCONFIG6581_H + +#include "FilterModelConfig.h" + +#include + +#include "Dac.h" + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +class Integrator6581; + +/** + * Calculate parameters for 6581 filter emulation. + */ +class FilterModelConfig6581 final : public FilterModelConfig +{ +private: + static const unsigned int DAC_BITS = 11; + +private: + static std::unique_ptr instance; + // This allows access to the private constructor +#ifdef HAVE_CXX11 + friend std::unique_ptr::deleter_type; +#else + friend class std::auto_ptr; +#endif + + /// Transistor parameters. + //@{ + const double WL_vcr; ///< W/L for VCR + const double WL_snake; ///< W/L for "snake" + //@} + + /// DAC parameters. + //@{ + const double dac_zero; + const double dac_scale; + //@} + + /// DAC lookup table + Dac dac; + + /// VCR - 6581 only. + //@{ + unsigned short vcr_nVg[1 << 16]; + unsigned short vcr_n_Ids_term[1 << 16]; + //@} + +private: + double getDacZero(double adjustment) const { return dac_zero + (1. - adjustment); } + + FilterModelConfig6581(); + ~FilterModelConfig6581() DEFAULT; + +public: + static FilterModelConfig6581* getInstance(); + + /** + * Construct an 11 bit cutoff frequency DAC output voltage table. + * Ownership is transferred to the requester which becomes responsible + * of freeing the object when done. + * + * @param adjustment + * @return the DAC table + */ + unsigned short* getDAC(double adjustment) const; + + /** + * Construct an integrator solver. + * + * @return the integrator + */ + std::unique_ptr buildIntegrator(); + + inline unsigned short getVcr_nVg(int i) const { return vcr_nVg[i]; } + inline unsigned short getVcr_n_Ids_term(int i) const { return vcr_n_Ids_term[i]; } + // only used if SLOPE_FACTOR is defined + inline double getUt() const { return Ut; } + inline double getN16() const { return N16; } +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/FilterModelConfig8580.cpp b/src/sound/resid-fp/FilterModelConfig8580.cpp new file mode 100644 index 0000000000..e838a366cc --- /dev/null +++ b/src/sound/resid-fp/FilterModelConfig8580.cpp @@ -0,0 +1,282 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "FilterModelConfig8580.h" + +#include "Integrator8580.h" +#include "OpAmp.h" + + +namespace reSIDfp +{ + +/* + * R1 = 15.3*Ri + * R2 = 7.3*Ri + * R3 = 4.7*Ri + * Rf = 1.4*Ri + * R4 = 1.4*Ri + * R8 = 2.0*Ri + * RC = 2.8*Ri + * + * res feedback input + * --- -------- ----- + * 0 Rf Ri + * 1 Rf|R1 Ri + * 2 Rf|R2 Ri + * 3 Rf|R3 Ri + * 4 Rf R4 + * 5 Rf|R1 R4 + * 6 Rf|R2 R4 + * 7 Rf|R3 R4 + * 8 Rf R8 + * 9 Rf|R1 R8 + * A Rf|R2 R8 + * B Rf|R3 R8 + * C Rf RC + * D Rf|R1 RC + * E Rf|R2 RC + * F Rf|R3 RC + */ +const double resGain[16] = +{ + 1.4/1.0, // Rf/Ri 1.4 + ((1.4*15.3)/(1.4+15.3))/1.0, // (Rf|R1)/Ri 1.28263 + ((1.4*7.3)/(1.4+7.3))/1.0, // (Rf|R2)/Ri 1.17471 + ((1.4*4.7)/(1.4+4.7))/1.0, // (Rf|R3)/Ri 1.07869 + 1.4/1.4, // Rf/R4 1 + ((1.4*15.3)/(1.4+15.3))/1.4, // (Rf|R1)/R4 0.916168 + ((1.4*7.3)/(1.4+7.3))/1.4, // (Rf|R2)/R4 0.83908 + ((1.4*4.7)/(1.4+4.7))/1.4, // (Rf|R3)/R4 0.770492 + 1.4/2.0, // Rf/R8 0.7 + ((1.4*15.3)/(1.4+15.3))/2.0, // (Rf|R1)/R8 0.641317 + ((1.4*7.3)/(1.4+7.3))/2.0, // (Rf|R2)/R8 0.587356 + ((1.4*4.7)/(1.4+4.7))/2.0, // (Rf|R3)/R8 0.539344 + 1.4/2.8, // Rf/RC 0.5 + ((1.4*15.3)/(1.4+15.3))/2.8, // (Rf|R1)/RC 0.458084 + ((1.4*7.3)/(1.4+7.3))/2.8, // (Rf|R2)/RC 0.41954 + ((1.4*4.7)/(1.4+4.7))/2.8, // (Rf|R3)/RC 0.385246 +}; + +const unsigned int OPAMP_SIZE = 21; + +/** + * This is the SID 8580 op-amp voltage transfer function, measured on + * CAP1B/CAP1A on a chip marked CSG 8580R5 1690 25. + */ +const Spline::Point opamp_voltage[OPAMP_SIZE] = +{ + { 1.30, 8.91 }, // Approximate start of actual range + { 4.76, 8.91 }, + { 4.77, 8.90 }, + { 4.78, 8.88 }, + { 4.785, 8.86 }, + { 4.79, 8.80 }, + { 4.795, 8.60 }, + { 4.80, 8.25 }, + { 4.805, 7.50 }, + { 4.81, 6.10 }, + { 4.815, 4.05 }, // Change of curvature + { 4.82, 2.27 }, + { 4.825, 1.65 }, + { 4.83, 1.55 }, + { 4.84, 1.47 }, + { 4.85, 1.43 }, + { 4.87, 1.37 }, + { 4.90, 1.34 }, + { 5.00, 1.30 }, + { 5.10, 1.30 }, + { 8.91, 1.30 }, // Approximate end of actual range +}; + +std::unique_ptr FilterModelConfig8580::instance(nullptr); + +FilterModelConfig8580* FilterModelConfig8580::getInstance() +{ + if (!instance.get()) + { + instance.reset(new FilterModelConfig8580()); + } + + return instance.get(); +} + +FilterModelConfig8580::FilterModelConfig8580() : + FilterModelConfig( + 0.30, // voice voltage range FIXME measure + 4.84, // voice DC voltage FIXME measure + 22e-9, // capacitor value + 9.09, // Vdd + 0.80, // Vth + 100e-6, // uCox + opamp_voltage, + OPAMP_SIZE + ) +{ + // Create lookup tables for gains / summers. +#ifndef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + +// #pragma omp parallel sections + { +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // The filter summer operates at n ~ 1, and has 5 fundamentally different + // input configurations (2 - 6 input "resistors"). + // + // Note that all "on" transistors are modeled as one. This is not + // entirely accurate, since the input for each transistor is different, + // and transistors are not linear components. However modeling all + // transistors separately would be extremely costly. + for (int i = 0; i < 5; i++) + { + const int idiv = 2 + i; // 2 - 6 input "resistors". + const int size = idiv << 16; + const double n = idiv; + opampModel.reset(); + summer[i] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16 / idiv; /* vmin .. vmax */ + summer[i][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // The audio mixer operates at n ~ 8/5, and has 8 fundamentally different + // input configurations (0 - 7 input "resistors"). + // + // All "on", transistors are modeled as one - see comments above for + // the filter summer. + for (int i = 0; i < 8; i++) + { + const int idiv = (i == 0) ? 1 : i; + const int size = (i == 0) ? 1 : i << 16; + const double n = i * 8.0 / 5.0; + opampModel.reset(); + mixer[i] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16 / idiv; /* vmin .. vmax */ + mixer[i][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // 4 bit "resistor" ladders in the audio output gain + // necessitate 16 gain tables. + // From die photographs of the volume "resistor" ladders + // it follows that gain ~ vol/16 (assuming ideal + // op-amps and ideal "resistors"). + for (int n8 = 0; n8 < 16; n8++) + { + const int size = 1 << 16; + const double n = n8 / 16.0; + opampModel.reset(); + gain_vol[n8] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16; /* vmin .. vmax */ + gain_vol[n8][vi] = getNormalizedValue(opampModel.solve(n, vin)); + } + } + } + +// #pragma omp section + { +#ifdef _OPENMP + OpAmp opampModel( + std::vector( + std::begin(opamp_voltage), + std::end(opamp_voltage)), + Vddt, + vmin, + vmax); +#endif + // 4 bit "resistor" ladders in the bandpass resonance gain + // necessitate 16 gain tables. + // From die photographs of the bandpass "resistor" ladders + // it follows that 1/Q ~ 2^((4 - res)/8) (assuming ideal + // op-amps and ideal "resistors"). + for (int n8 = 0; n8 < 16; n8++) + { + const int size = 1 << 16; + opampModel.reset(); + gain_res[n8] = new unsigned short[size]; + + for (int vi = 0; vi < size; vi++) + { + const double vin = vmin + vi / N16; /* vmin .. vmax */ + gain_res[n8][vi] = getNormalizedValue(opampModel.solve(resGain[n8], vin)); + } + } + } + } +} + +std::unique_ptr FilterModelConfig8580::buildIntegrator() +{ + return MAKE_UNIQUE(Integrator8580, this); +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/FilterModelConfig8580.h b/src/sound/resid-fp/FilterModelConfig8580.h new file mode 100644 index 0000000000..509171bc3f --- /dev/null +++ b/src/sound/resid-fp/FilterModelConfig8580.h @@ -0,0 +1,68 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef FILTERMODELCONFIG8580_H +#define FILTERMODELCONFIG8580_H + +#include "FilterModelConfig.h" + +#include + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +class Integrator8580; + +/** + * Calculate parameters for 8580 filter emulation. + */ +class FilterModelConfig8580 final : public FilterModelConfig +{ +private: + static std::unique_ptr instance; + // This allows access to the private constructor +#ifdef HAVE_CXX11 + friend std::unique_ptr::deleter_type; +#else + friend class std::auto_ptr; +#endif + +private: + FilterModelConfig8580(); + ~FilterModelConfig8580() DEFAULT; + +public: + static FilterModelConfig8580* getInstance(); + + /** + * Construct an integrator solver. + * + * @return the integrator + */ + std::unique_ptr buildIntegrator(); +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/INSTALL b/src/sound/resid-fp/INSTALL deleted file mode 100644 index 4573d6544b..0000000000 --- a/src/sound/resid-fp/INSTALL +++ /dev/null @@ -1,14 +0,0 @@ -Unless you want to do anything fancy, just say: - -% ./configure -% make - -ReSID-FP is compiled with a C++ compiler, so if you wish to specify compiler -and compiler flags you must set CXX and CXXFLAGS, e.g.: -% CXX=g++ CXXFLAGS="-g -O" ./configure - -In addition to normal configure flags, you may specify ---disable-inline - Disable inlining of functions (for debugging/profiling) - -ReSID-FP makes no installable files. The libresid.a is linked to final -executable automatically. diff --git a/src/sound/resid-fp/Integrator6581.cpp b/src/sound/resid-fp/Integrator6581.cpp new file mode 100644 index 0000000000..490be9b5c7 --- /dev/null +++ b/src/sound/resid-fp/Integrator6581.cpp @@ -0,0 +1,25 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2014 Leandro Nini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define INTEGRATOR_CPP + +#include "Integrator6581.h" + +// This is needed when compiling with --disable-inline diff --git a/src/sound/resid-fp/Integrator6581.h b/src/sound/resid-fp/Integrator6581.h new file mode 100644 index 0000000000..5bdeca37d8 --- /dev/null +++ b/src/sound/resid-fp/Integrator6581.h @@ -0,0 +1,285 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2022 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004, 2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef INTEGRATOR6581_H +#define INTEGRATOR6581_H + +#include "FilterModelConfig6581.h" + +#include +#include + +// uncomment to enable use of the slope factor +// in the EKV model +// actually produces worse results, needs investigation +//#define SLOPE_FACTOR + +#ifdef SLOPE_FACTOR +# include +#endif + +#include "siddefs-fp.h" + +namespace reSIDfp +{ + +/** + * Find output voltage in inverting integrator SID op-amp circuits, using a + * single fixpoint iteration step. + * + * A circuit diagram of a MOS 6581 integrator is shown below. + * + * +---C---+ + * | | + * vi --o--Rw--o-o--[A>--o-- vo + * | | vx + * +--Rs--+ + * + * From Kirchoff's current law it follows that + * + * IRw + IRs + ICr = 0 + * + * Using the formula for current through a capacitor, i = C*dv/dt, we get + * + * IRw + IRs + C*(vc - vc0)/dt = 0 + * dt/C*(IRw + IRs) + vc - vc0 = 0 + * vc = vc0 - n*(IRw(vi,vx) + IRs(vi,vx)) + * + * which may be rewritten as the following iterative fixpoint function: + * + * vc = vc0 - n*(IRw(vi,g(vc)) + IRs(vi,g(vc))) + * + * To accurately calculate the currents through Rs and Rw, we need to use + * transistor models. Rs has a gate voltage of Vdd = 12V, and can be + * assumed to always be in triode mode. For Rw, the situation is rather + * more complex, as it turns out that this transistor will operate in + * both subthreshold, triode, and saturation modes. + * + * The Shichman-Hodges transistor model routinely used in textbooks may + * be written as follows: + * + * Ids = 0 , Vgst < 0 (subthreshold mode) + * Ids = K*W/L*(2*Vgst - Vds)*Vds , Vgst >= 0, Vds < Vgst (triode mode) + * Ids = K*W/L*Vgst^2 , Vgst >= 0, Vds >= Vgst (saturation mode) + * + * where + * K = u*Cox/2 (transconductance coefficient) + * W/L = ratio between substrate width and length + * Vgst = Vg - Vs - Vt (overdrive voltage) + * + * This transistor model is also called the quadratic model. + * + * Note that the equation for the triode mode can be reformulated as + * independent terms depending on Vgs and Vgd, respectively, by the + * following substitution: + * + * Vds = Vgst - (Vgst - Vds) = Vgst - Vgdt + * + * Ids = K*W/L*(2*Vgst - Vds)*Vds + * = K*W/L*(2*Vgst - (Vgst - Vgdt)*(Vgst - Vgdt) + * = K*W/L*(Vgst + Vgdt)*(Vgst - Vgdt) + * = K*W/L*(Vgst^2 - Vgdt^2) + * + * This turns out to be a general equation which covers both the triode + * and saturation modes (where the second term is 0 in saturation mode). + * The equation is also symmetrical, i.e. it can calculate negative + * currents without any change of parameters (since the terms for drain + * and source are identical except for the sign). + * + * FIXME: Subthreshold as function of Vgs, Vgd. + * + * Ids = I0*W/L*e^(Vgst/(Ut/k)) , Vgst < 0 (subthreshold mode) + * + * where + * I0 = (2 * uCox * Ut^2) / k + * + * The remaining problem with the textbook model is that the transition + * from subthreshold to triode/saturation is not continuous. + * + * Realizing that the subthreshold and triode/saturation modes may both + * be defined by independent (and equal) terms of Vgs and Vds, + * respectively, the corresponding terms can be blended into (equal) + * continuous functions suitable for table lookup. + * + * The EKV model (Enz, Krummenacher and Vittoz) essentially performs this + * blending using an elegant mathematical formulation: + * + * Ids = Is * (if - ir) + * Is = ((2 * u*Cox * Ut^2)/k) * W/L + * if = ln^2(1 + e^((k*(Vg - Vt) - Vs)/(2*Ut)) + * ir = ln^2(1 + e^((k*(Vg - Vt) - Vd)/(2*Ut)) + * + * For our purposes, the EKV model preserves two important properties + * discussed above: + * + * - It consists of two independent terms, which can be represented by + * the same lookup table. + * - It is symmetrical, i.e. it calculates current in both directions, + * facilitating a branch-free implementation. + * + * Rw in the circuit diagram above is a VCR (voltage controlled resistor), + * as shown in the circuit diagram below. + * + * + * Vdd + * | + * Vdd _|_ + * | +---+ +---- Vw + * _|_ | + * +--+ +---o Vg + * | __|__ + * | ----- Rw + * | | | + * vi -----o------+ +-------- vo + * + * + * In order to calculalate the current through the VCR, its gate voltage + * must be determined. + * + * Assuming triode mode and applying Kirchoff's current law, we get the + * following equation for Vg: + * + * u*Cox/2*W/L*((nVddt - Vg)^2 - (nVddt - vi)^2 + (nVddt - Vg)^2 - (nVddt - Vw)^2) = 0 + * 2*(nVddt - Vg)^2 - (nVddt - vi)^2 - (nVddt - Vw)^2 = 0 + * (nVddt - Vg) = sqrt(((nVddt - vi)^2 + (nVddt - Vw)^2)/2) + * + * Vg = nVddt - sqrt(((nVddt - vi)^2 + (nVddt - Vw)^2)/2) + */ +class Integrator6581 +{ +private: + unsigned int nVddt_Vw_2; + mutable int vx; + mutable int vc; + +#ifdef SLOPE_FACTOR + // Slope factor n = 1/k + // where k is the gate coupling coefficient + // k = Cox/(Cox+Cdep) ~ 0.7 (depends on gate voltage) + mutable double n; +#endif + const unsigned short nVddt; + const unsigned short nVt; + const unsigned short nVmin; + const unsigned short nSnake; + + const FilterModelConfig6581* fmc; + +public: + Integrator6581(const FilterModelConfig6581* fmc, + double WL_snake) : + nVddt_Vw_2(0), + vx(0), + vc(0), +#ifdef SLOPE_FACTOR + n(1.4), +#endif + nVddt(fmc->getNormalizedValue(fmc->getVddt())), + nVt(fmc->getNormalizedValue(fmc->getVth())), + nVmin(fmc->getNVmin()), + nSnake(fmc->getNormalizedCurrentFactor(WL_snake)), + fmc(fmc) {} + + void setVw(unsigned short Vw) { nVddt_Vw_2 = ((nVddt - Vw) * (nVddt - Vw)) >> 1; } + + int solve(int vi) const; +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(INTEGRATOR_CPP) + +namespace reSIDfp +{ + +RESID_INLINE +int Integrator6581::solve(int vi) const +{ + // Make sure Vgst>0 so we're not in subthreshold mode + assert(vx < nVddt); + + // Check that transistor is actually in triode mode + // Vds < Vgs - Vth + assert(vi < nVddt); + + // "Snake" voltages for triode mode calculation. + const unsigned int Vgst = nVddt - vx; + const unsigned int Vgdt = nVddt - vi; + + const unsigned int Vgst_2 = Vgst * Vgst; + const unsigned int Vgdt_2 = Vgdt * Vgdt; + + // "Snake" current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30 + const int n_I_snake = nSnake * (static_cast(Vgst_2 - Vgdt_2) >> 15); + + // VCR gate voltage. // Scaled by m*2^16 + // Vg = Vddt - sqrt(((Vddt - Vw)^2 + Vgdt^2)/2) + const int nVg = static_cast(fmc->getVcr_nVg((nVddt_Vw_2 + (Vgdt_2 >> 1)) >> 16)); +#ifdef SLOPE_FACTOR + const double nVp = static_cast(nVg - nVt) / n; // Pinch-off voltage + const int kVgt = static_cast(nVp + 0.5) - nVmin; +#else + const int kVgt = (nVg - nVt) - nVmin; +#endif + + // VCR voltages for EKV model table lookup. + const int kVgt_Vs = (vx < kVgt) ? kVgt - vx : 0; + assert(kVgt_Vs < (1 << 16)); + const int kVgt_Vd = (vi < kVgt) ? kVgt - vi : 0; + assert(kVgt_Vd < (1 << 16)); + + // VCR current, scaled by m*2^15*2^15 = m*2^30 + const unsigned int If = static_cast(fmc->getVcr_n_Ids_term(kVgt_Vs)) << 15; + const unsigned int Ir = static_cast(fmc->getVcr_n_Ids_term(kVgt_Vd)) << 15; +#ifdef SLOPE_FACTOR + const double iVcr = static_cast(If - Ir); + const int n_I_vcr = static_cast(iVcr * n); +#else + const int n_I_vcr = If - Ir; +#endif + +#ifdef SLOPE_FACTOR + // estimate new slope factor based on gate voltage + const double gamma = 1.0; // body effect factor + const double phi = 0.8; // bulk Fermi potential + const double Vp = nVp / fmc->getN16(); + n = 1. + (gamma / (2. * sqrt(Vp + phi + 4. * fmc->getUt()))); + assert((n > 1.2) && (n < 1.8)); +#endif + + // Change in capacitor charge. + vc += n_I_snake + n_I_vcr; + + // vx = g(vc) + const int tmp = (vc >> 15) + (1 << 15); + assert(tmp < (1 << 16)); + vx = fmc->getOpampRev(tmp); + + // Return vo. + return vx - (vc >> 14); +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/Integrator8580.cpp b/src/sound/resid-fp/Integrator8580.cpp new file mode 100644 index 0000000000..6fba9521bc --- /dev/null +++ b/src/sound/resid-fp/Integrator8580.cpp @@ -0,0 +1,25 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2014-2016 Leandro Nini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define INTEGRATOR8580_CPP + +#include "Integrator8580.h" + +// This is needed when compiling with --disable-inline diff --git a/src/sound/resid-fp/Integrator8580.h b/src/sound/resid-fp/Integrator8580.h new file mode 100644 index 0000000000..db9e46b058 --- /dev/null +++ b/src/sound/resid-fp/Integrator8580.h @@ -0,0 +1,142 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004, 2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef INTEGRATOR8580_H +#define INTEGRATOR8580_H + +#include "FilterModelConfig8580.h" + +#include +#include + +#include "siddefs-fp.h" + +namespace reSIDfp +{ + +/** + * 8580 integrator + * + * +---C---+ + * | | + * vi -----Rfc---o--[A>--o-- vo + * vx + * + * IRfc + ICr = 0 + * IRfc + C*(vc - vc0)/dt = 0 + * dt/C*(IRfc) + vc - vc0 = 0 + * vc = vc0 - n*(IRfc(vi,vx)) + * vc = vc0 - n*(IRfc(vi,g(vc))) + * + * IRfc = K*W/L*(Vgst^2 - Vgdt^2) = n*((Vddt - vx)^2 - (Vddt - vi)^2) + * + * Rfc gate voltage is generated by an OP Amp and depends on chip temperature. + */ +class Integrator8580 +{ +private: + mutable int vx; + mutable int vc; + + unsigned short nVgt; + unsigned short n_dac; + + const FilterModelConfig8580* fmc; + +public: + Integrator8580(const FilterModelConfig8580* fmc) : + vx(0), + vc(0), + fmc(fmc) + { + setV(1.5); + } + + /** + * Set Filter Cutoff resistor ratio. + */ + void setFc(double wl) + { + // Normalized current factor, 1 cycle at 1MHz. + // Fit in 5 bits. + n_dac = fmc->getNormalizedCurrentFactor(wl); + } + + /** + * Set FC gate voltage multiplier. + */ + void setV(double v) + { + // Gate voltage is controlled by the switched capacitor voltage divider + // Ua = Ue * v = 4.76v 1 1.0 && v < 2.0); + const double Vg = 4.76 * v; + const double Vgt = Vg - fmc->getVth(); + + // Vg - Vth, normalized so that translated values can be subtracted: + // Vgt - x = (Vgt - t) - (x - t) + nVgt = fmc->getNormalizedValue(Vgt); + } + + int solve(int vi) const; +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(INTEGRATOR8580_CPP) + +namespace reSIDfp +{ + +RESID_INLINE +int Integrator8580::solve(int vi) const +{ + // Make sure we're not in subthreshold mode + assert(vx < nVgt); + + // DAC voltages + const unsigned int Vgst = nVgt - vx; + const unsigned int Vgdt = (vi < nVgt) ? nVgt - vi : 0; // triode/saturation mode + + const unsigned int Vgst_2 = Vgst * Vgst; + const unsigned int Vgdt_2 = Vgdt * Vgdt; + + // DAC current, scaled by (1/m)*2^13*m*2^16*m*2^16*2^-15 = m*2^30 + const int n_I_dac = n_dac * (static_cast(Vgst_2 - Vgdt_2) >> 15); + + // Change in capacitor charge. + vc += n_I_dac; + + // vx = g(vc) + const int tmp = (vc >> 15) + (1 << 15); + assert(tmp < (1 << 16)); + vx = fmc->getOpampRev(tmp); + + // Return vo. + return vx - (vc >> 14); +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/Makefile.am b/src/sound/resid-fp/Makefile.am deleted file mode 100644 index 5af2632293..0000000000 --- a/src/sound/resid-fp/Makefile.am +++ /dev/null @@ -1,29 +0,0 @@ -## Process this file with automake to create Makefile.in - -AR = @AR@ - -noinst_LIBRARIES = libresidfp.a - -libresidfp_a_SOURCES = sid.cc voice.cc wave.cc envelope.cc filter.cc extfilt.cc pot.cc version.cc convolve.cc $(noinst_DATA:.dat=.cc) - -BUILT_SOURCES = $(noinst_DATA:.dat=.cc) - -noinst_HEADERS = sid.h voice.h wave.h envelope.h filter.h extfilt.h pot.h - -noinst_DATA = wave6581_PST.dat wave6581_PS_.dat wave6581_P_T.dat wave6581__ST.dat wave8580_PST.dat wave8580_PS_.dat wave8580_P_T.dat wave8580__ST.dat - -noinst_SCRIPTS = samp2src.pl - -EXTRA_DIST = $(noinst_HEADERS) $(noinst_DATA) $(noinst_SCRIPTS) README.VICE convolve-sse.cc - -SUFFIXES = .dat - -.dat.cc: - $(PERL) $(srcdir)/samp2src.pl $* $< $(srcdir)/$@ - -if USE_SSE -convolve-sse.o: convolve-sse.cc - $(CXXCOMPILE) -msse -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< - -libresidfp_a_LIBADD = convolve-sse.o -endif diff --git a/src/sound/resid-fp/Makefile.in b/src/sound/resid-fp/Makefile.in deleted file mode 100644 index 5045f99a14..0000000000 --- a/src/sound/resid-fp/Makefile.in +++ /dev/null @@ -1,557 +0,0 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - - - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = . -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = . -DIST_COMMON = README $(am__configure_deps) $(noinst_HEADERS) \ - $(srcdir)/../../depcomp $(srcdir)/../../install-sh \ - $(srcdir)/../../missing $(srcdir)/../../mkinstalldirs \ - $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/siddefs-fp.h.in $(top_srcdir)/configure AUTHORS \ - COPYING ChangeLog INSTALL NEWS -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ - configure.lineno configure.status.lineno -mkinstalldirs = $(SHELL) $(top_srcdir)/../../mkinstalldirs -CONFIG_CLEAN_FILES = siddefs-fp.h -LIBRARIES = $(noinst_LIBRARIES) -ARFLAGS = cru -libresidfp_a_AR = $(AR) $(ARFLAGS) -@USE_SSE_TRUE@libresidfp_a_DEPENDENCIES = convolve-sse.o -am__objects_1 = wave6581_PST.$(OBJEXT) wave6581_PS_.$(OBJEXT) \ - wave6581_P_T.$(OBJEXT) wave6581__ST.$(OBJEXT) \ - wave8580_PST.$(OBJEXT) wave8580_PS_.$(OBJEXT) \ - wave8580_P_T.$(OBJEXT) wave8580__ST.$(OBJEXT) -am_libresidfp_a_OBJECTS = sid.$(OBJEXT) voice.$(OBJEXT) wave.$(OBJEXT) \ - envelope.$(OBJEXT) filter.$(OBJEXT) extfilt.$(OBJEXT) \ - pot.$(OBJEXT) version.$(OBJEXT) convolve.$(OBJEXT) \ - $(am__objects_1) -libresidfp_a_OBJECTS = $(am_libresidfp_a_OBJECTS) -SCRIPTS = $(noinst_SCRIPTS) -DEFAULT_INCLUDES = -I. -I$(srcdir) -depcomp = $(SHELL) $(top_srcdir)/../../depcomp -am__depfiles_maybe = depfiles -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -CXXLD = $(CXX) -CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ - -o $@ -SOURCES = $(libresidfp_a_SOURCES) -DIST_SOURCES = $(libresidfp_a_SOURCES) -DATA = $(noinst_DATA) -HEADERS = $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -distdir = $(PACKAGE)-$(VERSION) -top_distdir = $(distdir) -am__remove_distdir = \ - { test ! -d $(distdir) \ - || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr $(distdir); }; } -DIST_ARCHIVES = $(distdir).tar.gz -GZIP_ENV = --best -distuninstallcheck_listfiles = find . -type f -print -distcleancheck_listfiles = find . -type f -print -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GREP = @GREP@ -HAVE_EXPF_PROTOTYPE = @HAVE_EXPF_PROTOTYPE@ -HAVE_LOGF_PROTOTYPE = @HAVE_LOGF_PROTOTYPE@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PERL = @PERL@ -RANLIB = @RANLIB@ -RESID_HAVE_BOOL = @RESID_HAVE_BOOL@ -RESID_INLINE = @RESID_INLINE@ -RESID_USE_SSE = @RESID_USE_SSE@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_SSE_FALSE = @USE_SSE_FALSE@ -USE_SSE_TRUE = @USE_SSE_TRUE@ -VERSION = @VERSION@ -ac_ct_CXX = @ac_ct_CXX@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -noinst_LIBRARIES = libresidfp.a -libresidfp_a_SOURCES = sid.cc voice.cc wave.cc envelope.cc filter.cc extfilt.cc pot.cc version.cc convolve.cc $(noinst_DATA:.dat=.cc) -BUILT_SOURCES = $(noinst_DATA:.dat=.cc) -noinst_HEADERS = sid.h voice.h wave.h envelope.h filter.h extfilt.h pot.h -noinst_DATA = wave6581_PST.dat wave6581_PS_.dat wave6581_P_T.dat wave6581__ST.dat wave8580_PST.dat wave8580_PS_.dat wave8580_P_T.dat wave8580__ST.dat -noinst_SCRIPTS = samp2src.pl -EXTRA_DIST = $(noinst_HEADERS) $(noinst_DATA) $(noinst_SCRIPTS) README.VICE convolve-sse.cc -SUFFIXES = .dat -@USE_SSE_TRUE@libresidfp_a_LIBADD = convolve-sse.o -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am - -.SUFFIXES: -.SUFFIXES: .dat .cc .o .obj -am--refresh: - @: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ - cd $(srcdir) && $(AUTOMAKE) --gnu \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - echo ' $(SHELL) ./config.status'; \ - $(SHELL) ./config.status;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - $(SHELL) ./config.status --recheck - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(srcdir) && $(AUTOCONF) -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) -siddefs-fp.h: $(top_builddir)/config.status $(srcdir)/siddefs-fp.h.in - cd $(top_builddir) && $(SHELL) ./config.status $@ - -clean-noinstLIBRARIES: - -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) -libresidfp.a: $(libresidfp_a_OBJECTS) $(libresidfp_a_DEPENDENCIES) - -rm -f libresidfp.a - $(libresidfp_a_AR) libresidfp.a $(libresidfp_a_OBJECTS) $(libresidfp_a_LIBADD) - $(RANLIB) libresidfp.a - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/convolve.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/envelope.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extfilt.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pot.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sid.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/voice.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave6581_PST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave6581_PS_.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave6581_P_T.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave6581__ST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave8580_PST.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave8580_PS_.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave8580_P_T.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wave8580__ST.Po@am__quote@ - -.cc.o: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< - -.cc.obj: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` -uninstall-info-am: - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - $(am__remove_distdir) - mkdir $(distdir) - $(mkdir_p) $(distdir)/. $(distdir)/../.. - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done - -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ - ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ - ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ - || chmod -R a+r $(distdir) -dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 - $(am__remove_distdir) - -dist-tarZ: distdir - tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) - -dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) - -dist-zip: distdir - -rm -f $(distdir).zip - zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) - -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) - -# This target untars the dist file and tries a VPATH configuration. Then -# it guarantees that the distribution is self-contained by making another -# tarfile. -distcheck: dist - case '$(DIST_ARCHIVES)' in \ - *.tar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ - *.tar.bz2*) \ - bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.Z*) \ - uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ - *.shar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ - *.zip*) \ - unzip $(distdir).zip ;;\ - esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst - chmod a-w $(distdir) - dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ - && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ - && cd $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ - $(DISTCHECK_CONFIGURE_FLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ - && $(MAKE) $(AM_MAKEFLAGS) check \ - && $(MAKE) $(AM_MAKEFLAGS) install \ - && $(MAKE) $(AM_MAKEFLAGS) installcheck \ - && $(MAKE) $(AM_MAKEFLAGS) uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ - distuninstallcheck \ - && chmod -R a-w "$$dc_install_base" \ - && ({ \ - (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ - && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ - distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ - } || { rm -rf "$$dc_destdir"; exit 1; }) \ - && rm -rf "$$dc_destdir" \ - && $(MAKE) $(AM_MAKEFLAGS) dist \ - && rm -rf $(DIST_ARCHIVES) \ - && $(MAKE) $(AM_MAKEFLAGS) distcleancheck - $(am__remove_distdir) - @(echo "$(distdir) archives ready for distribution: "; \ - list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ - sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}' -distuninstallcheck: - @cd $(distuninstallcheck_dir) \ - && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ - || { echo "ERROR: files left after uninstall:" ; \ - if test -n "$(DESTDIR)"; then \ - echo " (check DESTDIR support)"; \ - fi ; \ - $(distuninstallcheck_listfiles) ; \ - exit 1; } >&2 -distcleancheck: distclean - @if test '$(srcdir)' = . ; then \ - echo "ERROR: distcleancheck can only run from a VPATH build" ; \ - exit 1 ; \ - fi - @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ - || { echo "ERROR: files left in build directory after distclean:" ; \ - $(distcleancheck_listfiles) ; \ - exit 1; } >&2 -check-am: all-am -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LIBRARIES) $(SCRIPTS) $(DATA) $(HEADERS) -installdirs: -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-am - -clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am - -distclean: distclean-am - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-info-am - -.PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ - clean-generic clean-noinstLIBRARIES ctags dist dist-all \ - dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip distcheck \ - distclean distclean-compile distclean-generic distclean-tags \ - distcleancheck distdir distuninstallcheck dvi dvi-am html \ - html-am info info-am install install-am install-data \ - install-data-am install-exec install-exec-am install-info \ - install-info-am install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ - uninstall-am uninstall-info-am - - -.dat.cc: - $(PERL) $(srcdir)/samp2src.pl $* $< $(srcdir)/$@ - -@USE_SSE_TRUE@convolve-sse.o: convolve-sse.cc -@USE_SSE_TRUE@ $(CXXCOMPILE) -msse -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/sound/resid-fp/NEWS b/src/sound/resid-fp/NEWS deleted file mode 100644 index 70b2d4f8ef..0000000000 --- a/src/sound/resid-fp/NEWS +++ /dev/null @@ -1 +0,0 @@ -See ChangeLog for information about new features. diff --git a/src/sound/resid-fp/OpAmp.cpp b/src/sound/resid-fp/OpAmp.cpp new file mode 100644 index 0000000000..b26b2efcb7 --- /dev/null +++ b/src/sound/resid-fp/OpAmp.cpp @@ -0,0 +1,84 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2015 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "OpAmp.h" + +#include + +#include "siddefs-fp.h" + +namespace reSIDfp +{ + +const double EPSILON = 1e-8; + +double OpAmp::solve(double n, double vi) const +{ + // Start off with an estimate of x and a root bracket [ak, bk]. + // f is decreasing, so that f(ak) > 0 and f(bk) < 0. + double ak = vmin; + double bk = vmax; + + const double a = n + 1.; + const double b = Vddt; + const double b_vi = (b > vi) ? (b - vi) : 0.; + const double c = n * (b_vi * b_vi); + + for (;;) + { + const double xk = x; + + // Calculate f and df. + + Spline::Point out = opamp->evaluate(x); + const double vo = out.x; + const double dvo = out.y; + + const double b_vx = (b > x) ? b - x : 0.; + const double b_vo = (b > vo) ? b - vo : 0.; + + // f = a*(b - vx)^2 - c - (b - vo)^2 + const double f = a * (b_vx * b_vx) - c - (b_vo * b_vo); + + // df = 2*((b - vo)*dvo - a*(b - vx)) + const double df = 2. * (b_vo * dvo - a * b_vx); + + // Newton-Raphson step: xk1 = xk - f(xk)/f'(xk) + x -= f / df; + + if (unlikely(fabs(x - xk) < EPSILON)) + { + out = opamp->evaluate(x); + return out.x; + } + + // Narrow down root bracket. + (f < 0. ? bk : ak) = xk; + + if (unlikely(x <= ak) || unlikely(x >= bk)) + { + // Bisection step (ala Dekker's method). + x = (ak + bk) * 0.5; + } + } +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/OpAmp.h b/src/sound/resid-fp/OpAmp.h new file mode 100644 index 0000000000..f048b1845f --- /dev/null +++ b/src/sound/resid-fp/OpAmp.h @@ -0,0 +1,121 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef OPAMP_H +#define OPAMP_H + +#include +#include + +#include "Spline.h" + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +/** + * Find output voltage in inverting gain and inverting summer SID op-amp + * circuits, using a combination of Newton-Raphson and bisection. + * + * +---R2--+ + * | | + * vi ---R1--o--[A>--o-- vo + * vx + * + * From Kirchoff's current law it follows that + * + * IR1f + IR2r = 0 + * + * Substituting the triode mode transistor model K*W/L*(Vgst^2 - Vgdt^2) + * for the currents, we get: + * + * n*((Vddt - vx)^2 - (Vddt - vi)^2) + (Vddt - vx)^2 - (Vddt - vo)^2 = 0 + * + * where n is the ratio between R1 and R2. + * + * Our root function f can thus be written as: + * + * f = (n + 1)*(Vddt - vx)^2 - n*(Vddt - vi)^2 - (Vddt - vo)^2 = 0 + * + * Using substitution constants + * + * a = n + 1 + * b = Vddt + * c = n*(Vddt - vi)^2 + * + * the equations for the root function and its derivative can be written as: + * + * f = a*(b - vx)^2 - c - (b - vo)^2 + * df = 2*((b - vo)*dvo - a*(b - vx)) + */ +class OpAmp +{ +private: + /// Current root position (cached as guess to speed up next iteration) + mutable double x; + + const double Vddt; + const double vmin; + const double vmax; + + std::unique_ptr const opamp; + +public: + /** + * Opamp input -> output voltage conversion + * + * @param opamp opamp mapping table as pairs of points (in -> out) + * @param Vddt transistor dt parameter (in volts) + * @param vmin + * @param vmax + */ + OpAmp(const std::vector &opamp, double Vddt, + double vmin, double vmax + ) : + x(0.), + Vddt(Vddt), + vmin(vmin), + vmax(vmax), + opamp(new Spline(opamp)) {} + + /** + * Reset root position + */ + void reset() const + { + x = vmin; + } + + /** + * Solve the opamp equation for input vi in loading context n + * + * @param n the ratio of input/output loading + * @param vi input voltage + * @return vo output voltage + */ + double solve(double n, double vi) const; +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/Potentiometer.h b/src/sound/resid-fp/Potentiometer.h new file mode 100644 index 0000000000..8b63df130e --- /dev/null +++ b/src/sound/resid-fp/Potentiometer.h @@ -0,0 +1,50 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2013 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright (C) 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef POTENTIOMETER_H +#define POTENTIOMETER_H + +namespace reSIDfp +{ + +/** + * Potentiometer representation. + * + * This class will probably never be implemented in any real way. + * + * @author Ken Händel + * @author Dag Lem + */ +class Potentiometer +{ +public: + /** + * Read paddle value. Not modeled. + * + * @return paddle value (always 0xff) + */ + unsigned char readPOT() const { return 0xff; } +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/README b/src/sound/resid-fp/README index ac4f4275e9..45d4bfb921 100644 --- a/src/sound/resid-fp/README +++ b/src/sound/resid-fp/README @@ -1,79 +1,20 @@ -Please refer to original ../resid/README file for general discussion what -ReSID is. +reSIDfp is a fork of Dag Lem's reSID 0.16, a reverse engineered software emulation +of the MOS6581/8580 SID (Sound Interface Device). -This is ReSID-FP, a fork of ReSID that has been adapted to floating point -numbers. Some SSE assembly is used for vector convolutions when both the CPU -and compiler support it. In addition, some liberties have been taken in the -frequency region > 20 kHz which should be inaudible to humans. +The project was started by Antti S. Lankila in order to improve SID emulation +with special focus on the 6581 filter. +The codebase has been later on ported to java by Ken Händel within the jsidplay2 project +and has seen further work by Antti Lankila. +It was then ported back to c++ and integrated with improvements from reSID 1.0 by Leandro Nini. -In the emulation front, several changes to the original ReSID (henceforth -classical ReSID) have been made. These changes are listed here: -Waveforms: +Main differences from reSID: -- Noise waveform control via test bit is now possible. - (Unknown: how long does it take for the noise bits to fade with test bit on?) - This is used in SounDemoN's Tamaking, Bojojoing, etc, and the patch to - implement it in ReSID is his. +* combined waveforms are emulated by a parametrized model based on samplings from Kevtris; +* envelope generator is implemented like in the real machine with a shift register; +* high quality resampling is done in two steps to allow computational savings using lower order filters; +* part of the calculations are done with floats instead of fixed point; +* interpolation is accomplished with Fritsch-Carlson method to preserve monotonicity. -- Waveform 0, the frozen DAC, is emulated, which should make the new 8-bit - sample player routine work. -- Envelope and waveform outputs contain approximation of the imperfect DACs - (Unknown: are there other significant effects that affect the analog waveform - before it goes into filter, which should be modelled?) - -- I changed voice DC offsets around for 6581 to better match my R4AR 3789. - -Envelope: - -- Performance work at envelope. Validation pending, should ensure that the new - code behaves 100% identically to the old one. - -Mixer: - -- Experimentally, a subtle negative offset is injected into the mixer through - ext-in pin. This part seems, however, physically incorrect and is likely - removed in the future. (The coupling capacitor external to the chip must - eliminate any DC offset, and the ext-in circuit inside the chip has nothing - that could generate offsets. In the meantime, this fix still helps 8580 - Netherworld to play more correctly.) - -- I removed the mixer_DC very subtle effect on 6581, as it already has 10x - more offsets elsewhere. - -Filter: - -- 6581 filter output contains approximation of the distortion effect -- 8580 filter output has bp flipped in phase with the other outputs -- 6581 resonance is slightly boosted. Potentially 8580 resonance needs to be - slightly stronger as well, as many songs show a bit more "punch" on the real - chip and one way to get more of that is increasing resonance. 10-20 % - increment is a practical maximum. - -The upshot of all this is that for i386/x86-64 hardware, ReSID-FP's more -complicated algorithms may not seem any more expensive than the original ReSID. -For high-quality modes, it is virtually certain that ReSID-FP is actually -faster. - -Meanwhile, emulation quality should be improved. If there are bugs, I'd like -to know about them. If the filter sounds wrong, I might be able to improve it, -too. - -Here are some problematic songs, to get a feel for what's left to do: - -- Markus Mueller: Mechanicus - * the distorted guitar effect is too distorted, but don't know how/why. - -- Galway: Wizball - * the initial lead punches through with too much distortion. The "toggle" - between the muffled and more intense sound is too hard, even if similar - things do occur on the chip. - -Undoubtedly, many more such examples will be found. However, samplings and such -are really valueable only if they can be made on a chip that I have modelled -for ReSID-FP. In practice I want to know about badly-playing chips, but might -conclude that it actually plays alright. At any event, information about sound -issues is welcome. - -alankila@bel.fi +reSIDfp is free software. See the file COPYING for copying permission. diff --git a/src/sound/resid-fp/README.VICE b/src/sound/resid-fp/README.VICE deleted file mode 100644 index 02072ce9e7..0000000000 --- a/src/sound/resid-fp/README.VICE +++ /dev/null @@ -1,14 +0,0 @@ -This version of reSID has been modified for use with VICE. It is based on the -work contained in the resid/ directory, with duplicate files removed. All -classes have been renamed with suffix FP to avoid link-time clashes with the -other RESID implementation. - -These files reuse some define terms also defined by resid. You should not mix -resid/* and resid-fp/* files in one compile unit, or the results are probably -invalid. - -In particular, libtool is not used to build the library, and there -might be some workarounds for various substandard compilers. - -Please get the original version if you want to use reSID in your own -project. diff --git a/src/sound/resid-fp/SID.cpp b/src/sound/resid-fp/SID.cpp new file mode 100644 index 0000000000..840d264e28 --- /dev/null +++ b/src/sound/resid-fp/SID.cpp @@ -0,0 +1,506 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2016 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define SID_CPP + +#include "sid.h" + +#include + +#include "array.h" +#include "Dac.h" +#include "Filter6581.h" +#include "Filter8580.h" +#include "Potentiometer.h" +#include "WaveformCalculator.h" +#include "resample/TwoPassSincResampler.h" +#include "resample/ZeroOrderResampler.h" + +namespace reSIDfp +{ + +const unsigned int ENV_DAC_BITS = 8; +const unsigned int OSC_DAC_BITS = 12; + +/** + * The waveform D/A converter introduces a DC offset in the signal + * to the envelope multiplying D/A converter. The "zero" level of + * the waveform D/A converter can be found as follows: + * + * Measure the "zero" voltage of voice 3 on the SID audio output + * pin, routing only voice 3 to the mixer ($d417 = $0b, $d418 = + * $0f, all other registers zeroed). + * + * Then set the sustain level for voice 3 to maximum and search for + * the waveform output value yielding the same voltage as found + * above. This is done by trying out different waveform output + * values until the correct value is found, e.g. with the following + * program: + * + * lda #$08 + * sta $d412 + * lda #$0b + * sta $d417 + * lda #$0f + * sta $d418 + * lda #$f0 + * sta $d414 + * lda #$21 + * sta $d412 + * lda #$01 + * sta $d40e + * + * ldx #$00 + * lda #$38 ; Tweak this to find the "zero" level + *l cmp $d41b + * bne l + * stx $d40e ; Stop frequency counter - freeze waveform output + * brk + * + * The waveform output range is 0x000 to 0xfff, so the "zero" + * level should ideally have been 0x800. In the measured chip, the + * waveform output "zero" level was found to be 0x380 (i.e. $d41b + * = 0x38) at an audio output voltage of 5.94V. + * + * With knowledge of the mixer op-amp characteristics, further estimates + * of waveform voltages can be obtained by sampling the EXT IN pin. + * From EXT IN samples, the corresponding waveform output can be found by + * using the model for the mixer. + * + * Such measurements have been done on a chip marked MOS 6581R4AR + * 0687 14, and the following results have been obtained: + * * The full range of one voice is approximately 1.5V. + * * The "zero" level rides at approximately 5.0V. + * + * + * zero-x did the measuring on the 8580 (https://sourceforge.net/p/vice-emu/bugs/1036/#c5b3): + * When it sits on basic from powerup it's at 4.72 + * Run 1.prg and check the output pin level. + * Then run 2.prg and adjust it until the output level is the same... + * 0x94-0xA8 gives me the same 4.72 1.prg shows. + * On another 8580 it's 0x90-0x9C + * Third chip 0x94-0xA8 + * Fourth chip 0x90-0xA4 + * On the 8580 that plays digis the output is 4.66 and 0x93 is the only value to reach that. + * To me that seems as regular 8580s have somewhat wide 0-level range, + * whereas that digi-compatible 8580 has it very narrow. + * On my 6581R4AR has 0x3A as the only value giving the same output level as 1.prg + */ +//@{ +unsigned int constexpr OFFSET_6581 = 0x380; +unsigned int constexpr OFFSET_8580 = 0x9c0; +//@} + +/** + * Bus value stays alive for some time after each operation. + * Values differs between chip models, the timings used here + * are taken from VICE [1]. + * See also the discussion "How do I reliably detect 6581/8580 sid?" on CSDb [2]. + * + * Results from real C64 (testprogs/SID/bitfade/delayfrq0.prg): + * + * (new SID) (250469/8580R5) (250469/8580R5) + * delayfrq0 ~7a000 ~108000 + * + * (old SID) (250407/6581) + * delayfrq0 ~01d00 + * + * [1]: http://sourceforge.net/p/vice-emu/patches/99/ + * [2]: http://noname.c64.org/csdb/forums/?roomid=11&topicid=29025&showallposts=1 + */ +//@{ +int constexpr BUS_TTL_6581 = 0x01d00; +int constexpr BUS_TTL_8580 = 0xa2000; +//@} + +SID::SID() : + filter6581(new Filter6581()), + filter8580(new Filter8580()), + externalFilter(new ExternalFilter()), + resampler(nullptr), + potX(new Potentiometer()), + potY(new Potentiometer()) +{ + voice[0].reset(new Voice()); + voice[1].reset(new Voice()); + voice[2].reset(new Voice()); + + muted[0] = muted[1] = muted[2] = false; + + reset(); + setChipModel(MOS8580); +} + +SID::~SID() +{ + // Needed to delete auto_ptr with complete type +} + +void SID::setFilter6581Curve(double filterCurve) +{ + filter6581->setFilterCurve(filterCurve); +} + +void SID::setFilter8580Curve(double filterCurve) +{ + filter8580->setFilterCurve(filterCurve); +} + +void SID::enableFilter(bool enable) +{ + filter6581->enable(enable); + filter8580->enable(enable); +} + +void SID::voiceSync(bool sync) +{ + if (sync) + { + // Synchronize the 3 waveform generators. + for (int i = 0; i < 3; i++) + { + voice[i]->wave()->synchronize(voice[(i + 1) % 3]->wave(), voice[(i + 2) % 3]->wave()); + } + } + + // Calculate the time to next voice sync + nextVoiceSync = std::numeric_limits::max(); + + for (int i = 0; i < 3; i++) + { + WaveformGenerator* const wave = voice[i]->wave(); + const unsigned int freq = wave->readFreq(); + + if (wave->readTest() || freq == 0 || !voice[(i + 1) % 3]->wave()->readSync()) + { + continue; + } + + const unsigned int accumulator = wave->readAccumulator(); + const unsigned int thisVoiceSync = ((0x7fffff - accumulator) & 0xffffff) / freq + 1; + + if (thisVoiceSync < nextVoiceSync) + { + nextVoiceSync = thisVoiceSync; + } + } +} + +void SID::setChipModel(ChipModel model) +{ + switch (model) + { + case MOS6581: + filter = filter6581.get(); + modelTTL = BUS_TTL_6581; + break; + + case MOS8580: + filter = filter8580.get(); + modelTTL = BUS_TTL_8580; + break; + + default: + throw SIDError("Unknown chip type"); + } + + this->model = model; + + // calculate waveform-related tables + matrix_t* wavetables = WaveformCalculator::getInstance()->getWaveTable(); + matrix_t* pulldowntables = WaveformCalculator::getInstance()->buildPulldownTable(model); + + // calculate envelope DAC table + { + Dac dacBuilder(ENV_DAC_BITS); + dacBuilder.kinkedDac(model); + + for (unsigned int i = 0; i < (1 << ENV_DAC_BITS); i++) + { + envDAC[i] = static_cast(dacBuilder.getOutput(i)); + } + } + + // calculate oscillator DAC table + const bool is6581 = model == MOS6581; + + { + Dac dacBuilder(OSC_DAC_BITS); + dacBuilder.kinkedDac(model); + + const double offset = dacBuilder.getOutput(is6581 ? OFFSET_6581 : OFFSET_8580); + + for (unsigned int i = 0; i < (1 << OSC_DAC_BITS); i++) + { + const double dacValue = dacBuilder.getOutput(i); + oscDAC[i] = static_cast(dacValue - offset); + } + } + + // set voice tables + for (int i = 0; i < 3; i++) + { + voice[i]->setEnvDAC(envDAC); + voice[i]->setWavDAC(oscDAC); + voice[i]->wave()->setModel(is6581); + voice[i]->wave()->setWaveformModels(wavetables); + voice[i]->wave()->setPulldownModels(pulldowntables); + } +} + +void SID::reset() +{ + for (int i = 0; i < 3; i++) + { + voice[i]->reset(); + } + + filter6581->reset(); + filter8580->reset(); + externalFilter->reset(); + + if (resampler.get()) + { + resampler->reset(); + } + + busValue = 0; + busValueTtl = 0; + voiceSync(false); +} + +void SID::input(int value) +{ + filter6581->input(value); + filter8580->input(value); +} + +unsigned char SID::read(int offset) +{ + switch (offset) + { + case 0x19: // X value of paddle + busValue = potX->readPOT(); + busValueTtl = modelTTL; + break; + + case 0x1a: // Y value of paddle + busValue = potY->readPOT(); + busValueTtl = modelTTL; + break; + + case 0x1b: // Voice #3 waveform output + busValue = voice[2]->wave()->readOSC(); + busValueTtl = modelTTL; + break; + + case 0x1c: // Voice #3 ADSR output + busValue = voice[2]->envelope()->readENV(); + busValueTtl = modelTTL; + break; + + default: + // Reading from a write-only or non-existing register + // makes the bus discharge faster. + // Emulate this by halving the residual TTL. + busValueTtl /= 2; + break; + } + + return busValue; +} + +void SID::write(int offset, unsigned char value) +{ + busValue = value; + busValueTtl = modelTTL; + + switch (offset) + { + case 0x00: // Voice #1 frequency (Low-byte) + voice[0]->wave()->writeFREQ_LO(value); + break; + + case 0x01: // Voice #1 frequency (High-byte) + voice[0]->wave()->writeFREQ_HI(value); + break; + + case 0x02: // Voice #1 pulse width (Low-byte) + voice[0]->wave()->writePW_LO(value); + break; + + case 0x03: // Voice #1 pulse width (bits #8-#15) + voice[0]->wave()->writePW_HI(value); + break; + + case 0x04: // Voice #1 control register + voice[0]->writeCONTROL_REG(muted[0] ? 0 : value); + break; + + case 0x05: // Voice #1 Attack and Decay length + voice[0]->envelope()->writeATTACK_DECAY(value); + break; + + case 0x06: // Voice #1 Sustain volume and Release length + voice[0]->envelope()->writeSUSTAIN_RELEASE(value); + break; + + case 0x07: // Voice #2 frequency (Low-byte) + voice[1]->wave()->writeFREQ_LO(value); + break; + + case 0x08: // Voice #2 frequency (High-byte) + voice[1]->wave()->writeFREQ_HI(value); + break; + + case 0x09: // Voice #2 pulse width (Low-byte) + voice[1]->wave()->writePW_LO(value); + break; + + case 0x0a: // Voice #2 pulse width (bits #8-#15) + voice[1]->wave()->writePW_HI(value); + break; + + case 0x0b: // Voice #2 control register + voice[1]->writeCONTROL_REG(muted[1] ? 0 : value); + break; + + case 0x0c: // Voice #2 Attack and Decay length + voice[1]->envelope()->writeATTACK_DECAY(value); + break; + + case 0x0d: // Voice #2 Sustain volume and Release length + voice[1]->envelope()->writeSUSTAIN_RELEASE(value); + break; + + case 0x0e: // Voice #3 frequency (Low-byte) + voice[2]->wave()->writeFREQ_LO(value); + break; + + case 0x0f: // Voice #3 frequency (High-byte) + voice[2]->wave()->writeFREQ_HI(value); + break; + + case 0x10: // Voice #3 pulse width (Low-byte) + voice[2]->wave()->writePW_LO(value); + break; + + case 0x11: // Voice #3 pulse width (bits #8-#15) + voice[2]->wave()->writePW_HI(value); + break; + + case 0x12: // Voice #3 control register + voice[2]->writeCONTROL_REG(muted[2] ? 0 : value); + break; + + case 0x13: // Voice #3 Attack and Decay length + voice[2]->envelope()->writeATTACK_DECAY(value); + break; + + case 0x14: // Voice #3 Sustain volume and Release length + voice[2]->envelope()->writeSUSTAIN_RELEASE(value); + break; + + case 0x15: // Filter cut off frequency (bits #0-#2) + filter6581->writeFC_LO(value); + filter8580->writeFC_LO(value); + break; + + case 0x16: // Filter cut off frequency (bits #3-#10) + filter6581->writeFC_HI(value); + filter8580->writeFC_HI(value); + break; + + case 0x17: // Filter control + filter6581->writeRES_FILT(value); + filter8580->writeRES_FILT(value); + break; + + case 0x18: // Volume and filter modes + filter6581->writeMODE_VOL(value); + filter8580->writeMODE_VOL(value); + break; + + default: + break; + } + + // Update voicesync just in case. + voiceSync(false); +} + +void SID::setSamplingParameters(double clockFrequency, SamplingMethod method, double samplingFrequency, double highestAccurateFrequency) +{ + externalFilter->setClockFrequency(clockFrequency); + + switch (method) + { + case DECIMATE: + resampler.reset(new ZeroOrderResampler(clockFrequency, samplingFrequency)); + break; + + case RESAMPLE: + resampler.reset(TwoPassSincResampler::create(clockFrequency, samplingFrequency, highestAccurateFrequency)); + break; + + default: + throw SIDError("Unknown sampling method"); + } +} + +void SID::clockSilent(unsigned int cycles) +{ + ageBusValue(cycles); + + while (cycles != 0) + { + int delta_t = std::min(nextVoiceSync, cycles); + + if (delta_t > 0) + { + for (int i = 0; i < delta_t; i++) + { + // clock waveform generators (can affect OSC3) + voice[0]->wave()->clock(); + voice[1]->wave()->clock(); + voice[2]->wave()->clock(); + + voice[0]->wave()->output(voice[2]->wave()); + voice[1]->wave()->output(voice[0]->wave()); + voice[2]->wave()->output(voice[1]->wave()); + + // clock ENV3 only + voice[2]->envelope()->clock(); + } + + cycles -= delta_t; + nextVoiceSync -= delta_t; + } + + if (nextVoiceSync == 0) + { + voiceSync(true); + } + } +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/Spline.cpp b/src/sound/resid-fp/Spline.cpp new file mode 100644 index 0000000000..50d55fef14 --- /dev/null +++ b/src/sound/resid-fp/Spline.cpp @@ -0,0 +1,119 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2015 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "Spline.h" + +#include +#include + +namespace reSIDfp +{ + +Spline::Spline(const std::vector &input) : + params(input.size()), + c(¶ms[0]) +{ + assert(input.size() > 2); + + const size_t coeffLength = input.size() - 1; + + std::vector dxs(coeffLength); + std::vector ms(coeffLength); + + // Get consecutive differences and slopes + for (size_t i = 0; i < coeffLength; i++) + { + assert(input[i].x < input[i + 1].x); + + const double dx = input[i + 1].x - input[i].x; + const double dy = input[i + 1].y - input[i].y; + dxs[i] = dx; + ms[i] = dy/dx; + } + + // Get degree-1 coefficients + params[0].c = ms[0]; + for (size_t i = 1; i < coeffLength; i++) + { + const double m = ms[i - 1]; + const double mNext = ms[i]; + if (m * mNext <= 0) + { + params[i].c = 0.0; + } + else + { + const double dx = dxs[i - 1]; + const double dxNext = dxs[i]; + const double common = dx + dxNext; + params[i].c = 3.0 * common / ((common + dxNext) / m + (common + dx) / mNext); + } + } + params[coeffLength].c = ms[coeffLength - 1]; + + // Get degree-2 and degree-3 coefficients + for (size_t i = 0; i < coeffLength; i++) + { + params[i].x1 = input[i].x; + params[i].x2 = input[i + 1].x; + params[i].d = input[i].y; + + const double c1 = params[i].c; + const double m = ms[i]; + const double invDx = 1.0 / dxs[i]; + const double common = c1 + params[i + 1].c - m - m; + params[i].b = (m - c1 - common) * invDx; + params[i].a = common * invDx * invDx; + } + + // Fix the upper range, because we interpolate outside original bounds if necessary. + params[coeffLength - 1].x2 = std::numeric_limits::max(); +} + +Spline::Point Spline::evaluate(double x) const +{ + if ((x < c->x1) || (x > c->x2)) + { + for (size_t i = 0; i < params.size(); i++) + { + if (x <= params[i].x2) + { + c = ¶ms[i]; + break; + } + } + } + + // Interpolate + const double diff = x - c->x1; + + Point out; + + // y = a*x^3 + b*x^2 + c*x + d + out.x = ((c->a * diff + c->b) * diff + c->c) * diff + c->d; + + // dy = 3*a*x^2 + 2*b*x + c + out.y = (3.0 * c->a * diff + 2.0 * c->b) * diff + c->c; + + return out; +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/Spline.h b/src/sound/resid-fp/Spline.h new file mode 100644 index 0000000000..6cc2b1edc0 --- /dev/null +++ b/src/sound/resid-fp/Spline.h @@ -0,0 +1,78 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2015 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SPLINE_H +#define SPLINE_H + +#include +#include + +namespace reSIDfp +{ + +/** + * Fritsch-Carlson monotone cubic spline interpolation. + * + * Based on the implementation from the [Monotone cubic interpolation] wikipedia page. + * + * [Monotone cubic interpolation]: https://en.wikipedia.org/wiki/Monotone_cubic_interpolation + */ +class Spline +{ +public: + typedef struct + { + double x; + double y; + } Point; + +private: + typedef struct + { + double x1; + double x2; + double a; + double b; + double c; + double d; + } Param; + + typedef std::vector ParamVector; + +private: + /// Interpolation parameters + ParamVector params; + + /// Last used parameters, cached for speed up + mutable ParamVector::const_pointer c; + +public: + Spline(const std::vector &input); + + /** + * Evaluate y and its derivative at given point x. + */ + Point evaluate(double x) const; +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/Voice.h b/src/sound/resid-fp/Voice.h new file mode 100644 index 0000000000..fc7ed41b70 --- /dev/null +++ b/src/sound/resid-fp/Voice.h @@ -0,0 +1,130 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2022 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef VOICE_H +#define VOICE_H + +#include + +#include "siddefs-fp.h" +#include "WaveformGenerator.h" +#include "EnvelopeGenerator.h" + +#include "sidcxx11.h" + +namespace reSIDfp +{ + +/** + * Representation of SID voice block. + */ +class Voice +{ +private: + std::unique_ptr const waveformGenerator; + + std::unique_ptr const envelopeGenerator; + + /// The DAC LUT for analog waveform output + float* wavDAC; //-V730_NOINIT this is initialized in the SID constructor + + /// The DAC LUT for analog envelope output + float* envDAC; //-V730_NOINIT this is initialized in the SID constructor + +public: + /** + * Amplitude modulated waveform output. + * + * The waveform DAC generates a voltage between virtual ground and Vdd + * (5-12 V for the 6581 and 4.75-9 V for the 8580) + * corresponding to oscillator state 0 .. 4095. + * + * The envelope DAC generates a voltage between waveform gen output and + * the virtual ground level, corresponding to envelope state 0 .. 255. + * + * Ideal range [-2048*255, 2047*255]. + * + * @param ringModulator Ring-modulator for waveform + * @return the voice analog output + */ + RESID_INLINE + int output(const WaveformGenerator* ringModulator) const + { + unsigned int const wav = waveformGenerator->output(ringModulator); + unsigned int const env = envelopeGenerator->output(); + + // DAC imperfections are emulated by using the digital output + // as an index into a DAC lookup table. + return static_cast(wavDAC[wav] * envDAC[env]); + } + + /** + * Constructor. + */ + Voice() : + waveformGenerator(new WaveformGenerator()), + envelopeGenerator(new EnvelopeGenerator()) {} + + /** + * Set the analog DAC emulation for waveform generator. + * Must be called before any operation. + * + * @param dac + */ + void setWavDAC(float* dac) { wavDAC = dac; } + + /** + * Set the analog DAC emulation for envelope. + * Must be called before any operation. + * + * @param dac + */ + void setEnvDAC(float* dac) { envDAC = dac; } + + WaveformGenerator* wave() const { return waveformGenerator.get(); } + + EnvelopeGenerator* envelope() const { return envelopeGenerator.get(); } + + /** + * Write control register. + * + * @param control Control register value. + */ + void writeCONTROL_REG(unsigned char control) + { + waveformGenerator->writeCONTROL_REG(control); + envelopeGenerator->writeCONTROL_REG(control); + } + + /** + * SID reset. + */ + void reset() + { + waveformGenerator->reset(); + envelopeGenerator->reset(); + } +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/WaveformCalculator.cpp b/src/sound/resid-fp/WaveformCalculator.cpp new file mode 100644 index 0000000000..74a93cce56 --- /dev/null +++ b/src/sound/resid-fp/WaveformCalculator.cpp @@ -0,0 +1,199 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "WaveformCalculator.h" + +#include + +namespace reSIDfp +{ + +WaveformCalculator* WaveformCalculator::getInstance() +{ + static WaveformCalculator instance; + return &instance; +} + +/** + * Parameters derived with the Monte Carlo method based on + * samplings by kevtris. Code and data available in the project repository [1]. + * + * The score here reported is the acoustic error + * calculated XORing the estimated and the sampled values. + * In parentheses the number of mispredicted bits. + * + * [1] https://github.com/libsidplayfp/combined-waveforms + */ +const CombinedWaveformConfig config[2][5] = +{ + { /* kevtris chip G (6581 R2) */ + {0.862147212f, 0.f, 10.8962431f, 2.50848103f }, // TS error 1941 (327/28672) + {0.932746708f, 2.07508397f, 1.03668225f, 1.14876997f }, // PT error 5992 (126/32768) + {0.860927045f, 2.43506575f, 0.908603609f, 1.07907593f }, // PS error 3693 (521/28672) + {0.741343081f, 0.0452554375f, 1.1439606f, 1.05711341f }, // PTS error 338 ( 29/28672) + {0.96f, 2.5f, 1.1f, 1.2f }, // NP guessed + }, + { /* kevtris chip V (8580 R5) */ + {0.715788841f, 0.f, 1.32999945f, 2.2172699f }, // TS error 928 (135/32768) + {0.93500334f, 1.05977178f, 1.08629429f, 1.43518543f }, // PT error 7991 (212/32768) + {0.920648575f, 0.943601072f, 1.13034654f, 1.41881108f }, // PS error 12566 (394/32768) + {0.90921098f, 0.979807794f, 0.942194462f, 1.40958893f }, // PTS error 2092 ( 60/32768) + {0.95f, 1.15f, 1.f, 1.45f }, // NP guessed + }, +}; + +typedef float (*distance_t)(float, int); + +// Distance functions +static float exponentialDistance(float distance, int i) +{ + return pow(distance, -i); +} + +#if 0 +MAYBE_UNUSED static float linearDistance(float distance, int i) +{ + return 1.f / (1.f + i * distance); +} +#endif + +#if 0 +MAYBE_UNUSED static float quadraticDistance(float distance, int i) +{ + return 1.f / (1.f + (i*i) * distance); +} +#endif + +/// Calculate triangle waveform +static unsigned int triXor(unsigned int val) +{ + return (((val & 0x800) == 0) ? val : (val ^ 0xfff)) << 1; +} + +/** + * Generate bitstate based on emulation of combined waves pulldown. + * + * @param distancetable + * @param pulsestrength + * @param threshold + * @param accumulator the high bits of the accumulator value + */ +short calculatePulldown(float distancetable[], float pulsestrength, float threshold, unsigned int accumulator) +{ + unsigned char bit[12]; + + for (unsigned int i = 0; i < 12; i++) + { + bit[i] = (accumulator & (1u << i)) != 0 ? 1 : 0; + } + + float pulldown[12]; + + for (int sb = 0; sb < 12; sb++) + { + float avg = 0.f; + float n = 0.f; + + for (int cb = 0; cb < 12; cb++) + { + if (cb == sb) + continue; + const float weight = distancetable[sb - cb + 12]; + avg += static_cast(1 - bit[cb]) * weight; + n += weight; + } + + avg -= pulsestrength; + + pulldown[sb] = avg / n; + } + + // Get the predicted value + short value = 0; + + for (unsigned int i = 0; i < 12; i++) + { + const float bitValue = bit[i] != 0 ? 1.f - pulldown[i] : 0.f; + if (bitValue > threshold) + { + value |= 1u << i; + } + } + + return value; +} + +WaveformCalculator::WaveformCalculator() : + wftable(4, 4096) +{ + // Build waveform table. + for (unsigned int idx = 0; idx < (1u << 12); idx++) + { + const short saw = static_cast(idx); + const short tri = static_cast(triXor(idx)); + + wftable[0][idx] = 0xfff; + wftable[1][idx] = tri; + wftable[2][idx] = saw; + wftable[3][idx] = saw & (saw << 1); + } +} + +matrix_t* WaveformCalculator::buildPulldownTable(ChipModel model) +{ + const CombinedWaveformConfig* cfgArray = config[model == MOS6581 ? 0 : 1]; + + cw_cache_t::iterator lb = PULLDOWN_CACHE.lower_bound(cfgArray); + + if (lb != PULLDOWN_CACHE.end() && !(PULLDOWN_CACHE.key_comp()(cfgArray, lb->first))) + { + return &(lb->second); + } + + matrix_t pdTable(5, 4096); + + for (int wav = 0; wav < 5; wav++) + { + const CombinedWaveformConfig& cfg = cfgArray[wav]; + + const distance_t distFunc = exponentialDistance; + + float distancetable[12 * 2 + 1]; + distancetable[12] = 1.f; + for (int i = 12; i > 0; i--) + { + distancetable[12-i] = distFunc(cfg.distance1, i); + distancetable[12+i] = distFunc(cfg.distance2, i); + } + + for (unsigned int idx = 0; idx < (1u << 12); idx++) + { + pdTable[wav][idx] = calculatePulldown(distancetable, cfg.pulsestrength, cfg.threshold, idx); + } + } +#ifdef HAVE_CXX11 + return &(PULLDOWN_CACHE.emplace_hint(lb, cw_cache_t::value_type(cfgArray, pdTable))->second); +#else + return &(PULLDOWN_CACHE.insert(lb, cw_cache_t::value_type(cfgArray, pdTable))->second); +#endif +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/WaveformCalculator.h b/src/sound/resid-fp/WaveformCalculator.h new file mode 100644 index 0000000000..4ad6772745 --- /dev/null +++ b/src/sound/resid-fp/WaveformCalculator.h @@ -0,0 +1,136 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef WAVEFORMCALCULATOR_h +#define WAVEFORMCALCULATOR_h + +#include + +#include "array.h" +#include "sidcxx11.h" +#include "siddefs-fp.h" + + +namespace reSIDfp +{ + +/** + * Combined waveform model parameters. + */ +typedef struct +{ + float threshold; + float pulsestrength; + float distance1; + float distance2; +} CombinedWaveformConfig; + +/** + * Combined waveform calculator for WaveformGenerator. + * By combining waveforms, the bits of each waveform are effectively short + * circuited. A zero bit in one waveform will result in a zero output bit + * (thus the infamous claim that the waveforms are AND'ed). + * However, a zero bit in one waveform may also affect the neighboring bits + * in the output. + * + * Example: + * + * 1 1 + * Bit # 1 0 9 8 7 6 5 4 3 2 1 0 + * ----------------------- + * Sawtooth 0 0 0 1 1 1 1 1 1 0 0 0 + * + * Triangle 0 0 1 1 1 1 1 1 0 0 0 0 + * + * AND 0 0 0 1 1 1 1 1 0 0 0 0 + * + * Output 0 0 0 0 1 1 1 0 0 0 0 0 + * + * + * Re-vectorized die photographs reveal the mechanism behind this behavior. + * Each waveform selector bit acts as a switch, which directly connects + * internal outputs into the waveform DAC inputs as follows: + * + * - Noise outputs the shift register bits to DAC inputs as described above. + * Each output is also used as input to the next bit when the shift register + * is shifted. Lower four bits are grounded. + * - Pulse connects a single line to all DAC inputs. The line is connected to + * either 5V (pulse on) or 0V (pulse off) at bit 11, and ends at bit 0. + * - Triangle connects the upper 11 bits of the (MSB EOR'ed) accumulator to the + * DAC inputs, so that DAC bit 0 = 0, DAC bit n = accumulator bit n - 1. + * - Sawtooth connects the upper 12 bits of the accumulator to the DAC inputs, + * so that DAC bit n = accumulator bit n. Sawtooth blocks out the MSB from + * the EOR used to generate the triangle waveform. + * + * We can thus draw the following conclusions: + * + * - The shift register may be written to by combined waveforms. + * - The pulse waveform interconnects all bits in combined waveforms via the + * pulse line. + * - The combination of triangle and sawtooth interconnects neighboring bits + * of the sawtooth waveform. + * + * Also in the 6581 the MSB of the oscillator, used as input for the + * triangle xor logic and the pulse adder's last bit, is connected directly + * to the waveform selector, while in the 8580 it is latched at sid_clk2 + * before being forwarded to the selector. Thus in the 6581 if the sawtooth MSB + * is pulled down it might affect the oscillator's adder + * driving the top bit low. + * + */ +class WaveformCalculator +{ +private: + typedef std::map cw_cache_t; + +private: + matrix_t wftable; + + cw_cache_t PULLDOWN_CACHE; + +private: + WaveformCalculator(); + +public: + /** + * Get the singleton instance. + */ + static WaveformCalculator* getInstance(); + + /** + * Get the waveform table for use by WaveformGenerator. + * + * @return Waveform table + */ + matrix_t* getWaveTable() { return &wftable; } + + /** + * Build pulldown table for use by WaveformGenerator. + * + * @param model Chip model to use + * @return Pulldown table + */ + matrix_t* buildPulldownTable(ChipModel model); +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/WaveformGenerator.cpp b/src/sound/resid-fp/WaveformGenerator.cpp new file mode 100644 index 0000000000..4c7a55b3d0 --- /dev/null +++ b/src/sound/resid-fp/WaveformGenerator.cpp @@ -0,0 +1,397 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define WAVEFORMGENERATOR_CPP + +#include "WaveformGenerator.h" + +namespace reSIDfp +{ + +/** + * Number of cycles after which the waveform output fades to 0 when setting + * the waveform register to 0. + * Values measured on warm chips (6581R3/R4 and 8580R5) + * checking OSC3. + * Times vary wildly with temperature and may differ + * from chip to chip so the numbers here represent + * only the big difference between the old and new models. + * + * See [VICE Bug #290](http://sourceforge.net/p/vice-emu/bugs/290/) + * and [VICE Bug #1128](http://sourceforge.net/p/vice-emu/bugs/1128/) + */ +// ~95ms +const unsigned int FLOATING_OUTPUT_TTL_6581R3 = 54000; +const unsigned int FLOATING_OUTPUT_FADE_6581R3 = 1400; +// ~1s +//const unsigned int FLOATING_OUTPUT_TTL_6581R4 = 1000000; +// ~1s +const unsigned int FLOATING_OUTPUT_TTL_8580R5 = 800000; +const unsigned int FLOATING_OUTPUT_FADE_8580R5 = 50000; + +/** + * Number of cycles after which the shift register is reset + * when the test bit is set. + * Values measured on warm chips (6581R3/R4 and 8580R5) + * checking OSC3. + * Times vary wildly with temperature and may differ + * from chip to chip so the numbers here represent + * only the big difference between the old and new models. + */ +// ~210ms +const unsigned int SHIFT_REGISTER_RESET_6581R3 = 50000; +const unsigned int SHIFT_REGISTER_FADE_6581R3 = 15000; +// ~2.15s +//const unsigned int SHIFT_REGISTER_RESET_6581R4 = 2150000; +// ~2.8s +const unsigned int SHIFT_REGISTER_RESET_8580R5 = 986000; +const unsigned int SHIFT_REGISTER_FADE_8580R5 = 314300; + +const unsigned int shift_mask = + ~( + (1u << 2) | // Bit 20 + (1u << 4) | // Bit 18 + (1u << 8) | // Bit 14 + (1u << 11) | // Bit 11 + (1u << 13) | // Bit 9 + (1u << 17) | // Bit 5 + (1u << 20) | // Bit 2 + (1u << 22) // Bit 0 + ); + +/* + * This is what happens when the lfsr is clocked: + * + * cycle 0: bit 19 of the accumulator goes from low to high, the noise register acts normally, + * the output may pulldown a bit; + * + * cycle 1: first phase of the shift, the bits are interconnected and the output of each bit + * is latched into the following. The output may overwrite the latched value. + * + * cycle 2: second phase of the shift, the latched value becomes active in the first + * half of the clock and from the second half the register returns to normal operation. + * + * When the test or reset lines are active the first phase is executed at every cyle + * until the signal is released triggering the second phase. + * + * | | bit n | bit n+1 + * | bit19 | latch output | latch output + * -----+-------+--------------+-------------- + * phi1 | 0 | A <-> A | B <-> B + * phi2 | 0 | A <-> A | B <-> B + * -----+-------+--------------+-------------- + * phi1 | 1 | A <-> A | B <-> B <- bit19 raises + * phi2 | 1 | A <-> A | B <-> B + * -----+-------+--------------+-------------- + * phi1 | 1 | X A --|-> A B <- shift phase 1 + * phi2 | 1 | X A --|-> A B + * -----+-------+--------------+-------------- + * phi1 | 1 | X --> X | A --> A <- shift phase 2 + * phi2 | 1 | X <-> X | A <-> A + */ + +inline bool do_writeback(unsigned int waveform_old, unsigned int waveform_new, bool is6581) +{ + // no writeback without combined waveforms + if (waveform_new <= 8) + return false; + if (waveform_old <= 8) + return false; // fixes SID/noisewriteback/noise_writeback_test2-{old,new} + + // What's happening here? + if (is6581 && + ((((waveform_old & 0x3) == 0x1) && ((waveform_new & 0x3) == 0x2)) + || (((waveform_old & 0x3) == 0x2) && ((waveform_new & 0x3) == 0x1)))) + { + // fixes + // noise_writeback_check_9_to_A_old + // noise_writeback_check_9_to_E_old + // noise_writeback_check_A_to_9_old + // noise_writeback_check_A_to_D_old + // noise_writeback_check_D_to_A_old + // noise_writeback_check_E_to_9_old + return false; + } + if (waveform_old == 0xc) + { + // fixes + // noise_writeback_check_C_to_A_new + return false; + } + if (waveform_new == 0xc) + { + // fixes + // noise_writeback_check_9_to_C_old + // noise_writeback_check_A_to_C_old + return false; + } + + // ok do the writeback + return true; +} + +inline unsigned int get_noise_writeback(unsigned int waveform_output) +{ + return + ((waveform_output & (1u << 11)) >> 9) | // Bit 11 -> bit 20 + ((waveform_output & (1u << 10)) >> 6) | // Bit 10 -> bit 18 + ((waveform_output & (1u << 9)) >> 1) | // Bit 9 -> bit 14 + ((waveform_output & (1u << 8)) << 3) | // Bit 8 -> bit 11 + ((waveform_output & (1u << 7)) << 6) | // Bit 7 -> bit 9 + ((waveform_output & (1u << 6)) << 11) | // Bit 6 -> bit 5 + ((waveform_output & (1u << 5)) << 15) | // Bit 5 -> bit 2 + ((waveform_output & (1u << 4)) << 18); // Bit 4 -> bit 0 +} + +/* + * Perform the actual shifting, moving the latched value into following bits. + * The XORing for bit0 is done in this cycle using the test bit latched during + * the previous phi2 cycle. + */ +void WaveformGenerator::shift_phase2(unsigned int waveform_old, unsigned int waveform_new) +{ + if (do_writeback(waveform_old, waveform_new, is6581)) + { + // if noise is combined with another waveform the output drives the SR bits + shift_latch = (shift_register & shift_mask) | get_noise_writeback(waveform_output); + } + + // bit0 = (bit22 | test | reset) ^ bit17 = 1 ^ bit17 = ~bit17 + const unsigned int bit22 = ((test_or_reset ? 1 : 0) | shift_latch) << 22; + const unsigned int bit0 = (bit22 ^ (shift_latch << 17)) & (1 << 22); + + shift_register = (shift_latch >> 1) | bit0; +#ifdef TRACE + std::cout << std::hex << shift_latch << " -> " << shift_register << std::endl; +#endif + set_noise_output(); +} + +void WaveformGenerator::write_shift_register() +{ + if (unlikely(waveform > 0x8)) + { + if (waveform == 0xc) + return; // breaks SID/wf12nsr/wf12nsr + + // Write changes to the shift register output caused by combined waveforms + // back into the shift register. + if (likely(shift_pipeline != 1) && !test) + { +#ifdef TRACE + std::cout << "write shift_register" << std::endl; +#endif + // the output pulls down the SR bits + shift_register = shift_register & (shift_mask | get_noise_writeback(waveform_output)); + noise_output &= waveform_output; + } + else + { +#ifdef TRACE + std::cout << "write shift_latch" << std::endl; +#endif + // shift phase 1: the output drives the SR bits + noise_output = waveform_output; + } + + set_no_noise_or_noise_output(); + } +} + +void WaveformGenerator::set_noise_output() +{ + noise_output = + ((shift_register & (1u << 2)) << 9) | // Bit 20 -> bit 11 + ((shift_register & (1u << 4)) << 6) | // Bit 18 -> bit 10 + ((shift_register & (1u << 8)) << 1) | // Bit 14 -> bit 9 + ((shift_register & (1u << 11)) >> 3) | // Bit 11 -> bit 8 + ((shift_register & (1u << 13)) >> 6) | // Bit 9 -> bit 7 + ((shift_register & (1u << 17)) >> 11) | // Bit 5 -> bit 6 + ((shift_register & (1u << 20)) >> 15) | // Bit 2 -> bit 5 + ((shift_register & (1u << 22)) >> 18); // Bit 0 -> bit 4 + + set_no_noise_or_noise_output(); +} + +void WaveformGenerator::setWaveformModels(matrix_t* models) +{ + model_wave = models; +} + +void WaveformGenerator::setPulldownModels(matrix_t* models) +{ + model_pulldown = models; +} + +void WaveformGenerator::synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const +{ + // A special case occurs when a sync source is synced itself on the same + // cycle as when its MSB is set high. In this case the destination will + // not be synced. This has been verified by sampling OSC3. + if (unlikely(msb_rising) && syncDest->sync && !(sync && syncSource->msb_rising)) + { + syncDest->accumulator = 0; + } +} + +void WaveformGenerator::set_no_noise_or_noise_output() +{ + no_noise_or_noise_output = no_noise | noise_output; +} + +void WaveformGenerator::writeCONTROL_REG(unsigned char control) +{ + const unsigned int waveform_prev = waveform; + const bool test_prev = test; + + waveform = (control >> 4) & 0x0f; + test = (control & 0x08) != 0; + sync = (control & 0x02) != 0; + + // Substitution of accumulator MSB when sawtooth = 0, ring_mod = 1. + ring_msb_mask = ((~control >> 5) & (control >> 2) & 0x1) << 23; + + if (waveform != waveform_prev) + { + // Set up waveform tables + wave = (*model_wave)[waveform & 0x3]; + // We assume tha combinations including noise + // behave the same as without + switch (waveform & 0x7) + { + case 3: + pulldown = (*model_pulldown)[0]; + break; + case 4: + pulldown = (waveform & 0x8) ? (*model_pulldown)[4] : nullptr; + break; + case 5: + pulldown = (*model_pulldown)[1]; + break; + case 6: + pulldown = (*model_pulldown)[2]; + break; + case 7: + pulldown = (*model_pulldown)[3]; + break; + default: + pulldown = nullptr; + break; + } + + // no_noise and no_pulse are used in set_waveform_output() as bitmasks to + // only let the noise or pulse influence the output when the noise or pulse + // waveforms are selected. + no_noise = (waveform & 0x8) != 0 ? 0x000 : 0xfff; + set_no_noise_or_noise_output(); + no_pulse = (waveform & 0x4) != 0 ? 0x000 : 0xfff; + + if (waveform == 0) + { + // Change to floating DAC input. + // Reset fading time for floating DAC input. + floating_output_ttl = is6581 ? FLOATING_OUTPUT_TTL_6581R3 : FLOATING_OUTPUT_TTL_8580R5; + } + } + + if (test != test_prev) + { + if (test) + { + // Reset accumulator. + accumulator = 0; + + // Flush shift pipeline. + shift_pipeline = 0; + + // Latch the shift register value. + shift_latch = shift_register; +#ifdef TRACE + std::cout << "shift phase 1 (test)" << std::endl; +#endif + + // Set reset time for shift register. + shift_register_reset = is6581 ? SHIFT_REGISTER_RESET_6581R3 : SHIFT_REGISTER_RESET_8580R5; + } + else + { + // When the test bit is falling, the second phase of the shift is + // completed by enabling SRAM write. + shift_phase2(waveform_prev, waveform); + } + } +} + +void WaveformGenerator::waveBitfade() +{ + waveform_output &= waveform_output >> 1; + osc3 = waveform_output; + if (waveform_output != 0) + floating_output_ttl = is6581 ? FLOATING_OUTPUT_FADE_6581R3 : FLOATING_OUTPUT_FADE_8580R5; +} + +void WaveformGenerator::shiftregBitfade() +{ + shift_register |= shift_register >> 1; + shift_register |= 0x400000; + if (shift_register != 0x7fffff) + shift_register_reset = is6581 ? SHIFT_REGISTER_FADE_6581R3 : SHIFT_REGISTER_FADE_8580R5; +} + +void WaveformGenerator::reset() +{ + // accumulator is not changed on reset + freq = 0; + pw = 0; + + msb_rising = false; + + waveform = 0; + osc3 = 0; + + test = false; + sync = false; + + wave = model_wave ? (*model_wave)[0] : nullptr; + pulldown = nullptr; + + ring_msb_mask = 0; + no_noise = 0xfff; + no_pulse = 0xfff; + pulse_output = 0xfff; + + shift_register_reset = 0; + shift_register = 0x7fffff; + // when reset is released the shift register is clocked once + // so the lower bit is zeroed out + // bit0 = (bit22 | test) ^ bit17 = 1 ^ 1 = 0 + test_or_reset = true; + shift_latch = shift_register; + shift_phase2(0, 0); + + shift_pipeline = 0; + + waveform_output = 0; + floating_output_ttl = 0; +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/WaveformGenerator.h b/src/sound/resid-fp/WaveformGenerator.h new file mode 100644 index 0000000000..adca6c2281 --- /dev/null +++ b/src/sound/resid-fp/WaveformGenerator.h @@ -0,0 +1,440 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2023 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004,2010 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef WAVEFORMGENERATOR_H +#define WAVEFORMGENERATOR_H + +#include "siddefs-fp.h" +#include "array.h" + +#include "sidcxx11.h" + +// print SR debugging info +//#define TRACE 1 + +#ifdef TRACE +# include +#endif + +namespace reSIDfp +{ + +/** + * A 24 bit accumulator is the basis for waveform generation. + * FREQ is added to the lower 16 bits of the accumulator each cycle. + * The accumulator is set to zero when TEST is set, and starts counting + * when TEST is cleared. + * + * Waveforms are generated as follows: + * + * - No waveform: + * When no waveform is selected, the DAC input is floating. + * + * + * - Triangle: + * The upper 12 bits of the accumulator are used. + * The MSB is used to create the falling edge of the triangle by inverting + * the lower 11 bits. The MSB is thrown away and the lower 11 bits are + * left-shifted (half the resolution, full amplitude). + * Ring modulation substitutes the MSB with MSB EOR NOT sync_source MSB. + * + * + * - Sawtooth: + * The output is identical to the upper 12 bits of the accumulator. + * + * + * - Pulse: + * The upper 12 bits of the accumulator are used. + * These bits are compared to the pulse width register by a 12 bit digital + * comparator; output is either all one or all zero bits. + * The pulse setting is delayed one cycle after the compare. + * The test bit, when set to one, holds the pulse waveform output at 0xfff + * regardless of the pulse width setting. + * + * + * - Noise: + * The noise output is taken from intermediate bits of a 23-bit shift register + * which is clocked by bit 19 of the accumulator. + * The shift is delayed 2 cycles after bit 19 is set high. + * + * Operation: Calculate EOR result, shift register, set bit 0 = result. + * + * reset +--------------------------------------------+ + * | | | + * test--OR-->EOR<--+ | + * | | | + * 2 2 2 1 1 1 1 1 1 1 1 1 1 | + * Register bits: 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 <---+ + * | | | | | | | | + * Waveform bits: 1 1 9 8 7 6 5 4 + * 1 0 + * + * The low 4 waveform bits are zero (grounded). + */ +class WaveformGenerator +{ +private: + matrix_t* model_wave; + matrix_t* model_pulldown; + + short* wave; + short* pulldown; + + // PWout = (PWn/40.95)% + unsigned int pw; + + unsigned int shift_register; + + /// Shift register is latched when transitioning to shift phase 1. + unsigned int shift_latch; + + /// Emulation of pipeline causing bit 19 to clock the shift register. + int shift_pipeline; + + unsigned int ring_msb_mask; + unsigned int no_noise; + unsigned int noise_output; + unsigned int no_noise_or_noise_output; + unsigned int no_pulse; + unsigned int pulse_output; + + /// The control register right-shifted 4 bits; used for output function table lookup. + unsigned int waveform; + + unsigned int waveform_output; + + /// Current accumulator value. + unsigned int accumulator; + + // Fout = (Fn*Fclk/16777216)Hz + unsigned int freq; + + /// 8580 tri/saw pipeline + unsigned int tri_saw_pipeline; + + /// The OSC3 value + unsigned int osc3; + + /// Remaining time to fully reset shift register. + unsigned int shift_register_reset; + + // The wave signal TTL when no waveform is selected. + unsigned int floating_output_ttl; + + /// The control register bits. Gate is handled by EnvelopeGenerator. + //@{ + bool test; + bool sync; + //@} + + /// Test bit is latched at phi2 for the noise XOR. + bool test_or_reset; + + /// Tell whether the accumulator MSB was set high on this cycle. + bool msb_rising; + + bool is6581; //-V730_NOINIT this is initialized in the SID constructor + +private: + void shift_phase2(unsigned int waveform_old, unsigned int waveform_new); + + void write_shift_register(); + + void set_noise_output(); + + void set_no_noise_or_noise_output(); + + void waveBitfade(); + + void shiftregBitfade(); + +public: + void setWaveformModels(matrix_t* models); + void setPulldownModels(matrix_t* models); + + /** + * Set the chip model. + * Must be called before any operation. + * + * @param is6581 true if MOS6581, false if CSG8580 + */ + void setModel(bool is6581) { this->is6581 = is6581; } + + /** + * SID clocking. + */ + void clock(); + + /** + * Synchronize oscillators. + * This must be done after all the oscillators have been clock()'ed, + * so that they are in the same state. + * + * @param syncDest The oscillator that will be synced + * @param syncSource The sync source oscillator + */ + void synchronize(WaveformGenerator* syncDest, const WaveformGenerator* syncSource) const; + + /** + * Constructor. + */ + WaveformGenerator() : + model_wave(nullptr), + model_pulldown(nullptr), + wave(nullptr), + pulldown(nullptr), + pw(0), + shift_register(0), + shift_pipeline(0), + ring_msb_mask(0), + no_noise(0), + noise_output(0), + no_noise_or_noise_output(0), + no_pulse(0), + pulse_output(0), + waveform(0), + waveform_output(0), + accumulator(0x555555), // Accumulator's even bits are high on powerup + freq(0), + tri_saw_pipeline(0x555), + osc3(0), + shift_register_reset(0), + floating_output_ttl(0), + test(false), + sync(false), + msb_rising(false) {} + + /** + * Write FREQ LO register. + * + * @param freq_lo low 8 bits of frequency + */ + void writeFREQ_LO(unsigned char freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); } + + /** + * Write FREQ HI register. + * + * @param freq_hi high 8 bits of frequency + */ + void writeFREQ_HI(unsigned char freq_hi) { freq = (freq_hi << 8 & 0xff00) | (freq & 0xff); } + + /** + * Write PW LO register. + * + * @param pw_lo low 8 bits of pulse width + */ + void writePW_LO(unsigned char pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); } + + /** + * Write PW HI register. + * + * @param pw_hi high 8 bits of pulse width + */ + void writePW_HI(unsigned char pw_hi) { pw = (pw_hi << 8 & 0xf00) | (pw & 0x0ff); } + + /** + * Write CONTROL REGISTER register. + * + * @param control control register value + */ + void writeCONTROL_REG(unsigned char control); + + /** + * SID reset. + */ + void reset(); + + /** + * 12-bit waveform output. + * + * @param ringModulator The oscillator ring-modulating current one. + * @return the waveform generator digital output + */ + unsigned int output(const WaveformGenerator* ringModulator); + + /** + * Read OSC3 value. + */ + unsigned char readOSC() const { return static_cast(osc3 >> 4); } + + /** + * Read accumulator value. + */ + unsigned int readAccumulator() const { return accumulator; } + + /** + * Read freq value. + */ + unsigned int readFreq() const { return freq; } + + /** + * Read test value. + */ + bool readTest() const { return test; } + + /** + * Read sync value. + */ + bool readSync() const { return sync; } +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(WAVEFORMGENERATOR_CPP) + +namespace reSIDfp +{ + +RESID_INLINE +void WaveformGenerator::clock() +{ + if (unlikely(test)) + { + if (unlikely(shift_register_reset != 0) && unlikely(--shift_register_reset == 0)) + { +#ifdef TRACE + std::cout << "shiftregBitfade" << std::endl; +#endif + shiftregBitfade(); + shift_latch = shift_register; + + // New noise waveform output. + set_noise_output(); + } + + // Latch the test bit value for shift phase 2. + test_or_reset = true; + + // The test bit sets pulse high. + pulse_output = 0xfff; + } + else + { + // Calculate new accumulator value; + const unsigned int accumulator_old = accumulator; + accumulator = (accumulator + freq) & 0xffffff; + + // Check which bit have changed from low to high + const unsigned int accumulator_bits_set = ~accumulator_old & accumulator; + + // Check whether the MSB is set high. This is used for synchronization. + msb_rising = (accumulator_bits_set & 0x800000) != 0; + + // Shift noise register once for each time accumulator bit 19 is set high. + // The shift is delayed 2 cycles. + if (unlikely((accumulator_bits_set & 0x080000) != 0)) + { + // Pipeline: Detect rising bit, shift phase 1, shift phase 2. + shift_pipeline = 2; + } + else if (unlikely(shift_pipeline != 0)) + { + switch (--shift_pipeline) + { + case 0: +#ifdef TRACE + std::cout << "shift phase 2" << std::endl; +#endif + shift_phase2(waveform, waveform); + break; + case 1: +#ifdef TRACE + std::cout << "shift phase 1" << std::endl; +#endif + // Start shift phase 1. + test_or_reset = false; + shift_latch = shift_register; + break; + } + } + } +} + +RESID_INLINE +unsigned int WaveformGenerator::output(const WaveformGenerator* ringModulator) +{ + // Set output value. + if (likely(waveform != 0)) + { + const unsigned int ix = (accumulator ^ (~ringModulator->accumulator & ring_msb_mask)) >> 12; + + // The bit masks no_pulse and no_noise are used to achieve branch-free + // calculation of the output value. + waveform_output = wave[ix] & (no_pulse | pulse_output) & no_noise_or_noise_output; + if (pulldown != nullptr) + waveform_output = pulldown[waveform_output]; + + // Triangle/Sawtooth output is delayed half cycle on 8580. + // This will appear as a one cycle delay on OSC3 as it is latched + // in the first phase of the clock. + if ((waveform & 3) && !is6581) + { + osc3 = tri_saw_pipeline & (no_pulse | pulse_output) & no_noise_or_noise_output; + if (pulldown != nullptr) + osc3 = pulldown[osc3]; + tri_saw_pipeline = wave[ix]; + } + else + { + osc3 = waveform_output; + } + + // In the 6581 the top bit of the accumulator may be driven low by combined waveforms + // when the sawtooth is selected + if (is6581 + && (waveform & 0x2) + && ((waveform_output & 0x800) == 0)) + accumulator &= 0x7fffff; + + write_shift_register(); + } + else + { + // Age floating DAC input. + if (likely(floating_output_ttl != 0) && unlikely(--floating_output_ttl == 0)) + { + waveBitfade(); + } + } + + // The pulse level is defined as (accumulator >> 12) >= pw ? 0xfff : 0x000. + // The expression -((accumulator >> 12) >= pw) & 0xfff yields the same + // results without any branching (and thus without any pipeline stalls). + // NB! This expression relies on that the result of a boolean expression + // is either 0 or 1, and furthermore requires two's complement integer. + // A few more cycles may be saved by storing the pulse width left shifted + // 12 bits, and dropping the and with 0xfff (this is valid since pulse is + // used as a bit mask on 12 bit values), yielding the expression + // -(accumulator >= pw24). However this only results in negligible savings. + + // The result of the pulse width compare is delayed one cycle. + // Push next pulse level into pulse level pipeline. + pulse_output = ((accumulator >> 12) >= pw) ? 0xfff : 0x000; + + return waveform_output; +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/aclocal.m4 b/src/sound/resid-fp/aclocal.m4 deleted file mode 100644 index aef181a6dd..0000000000 --- a/src/sound/resid-fp/aclocal.m4 +++ /dev/null @@ -1,850 +0,0 @@ -# generated automatically by aclocal 1.9.6 -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005 Free Software Foundation, Inc. -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_AUTOMAKE_VERSION(VERSION) -# ---------------------------- -# Automake X.Y traces this macro to ensure aclocal.m4 has been -# generated from the m4 files accompanying Automake X.Y. -AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.9"]) - -# AM_SET_CURRENT_AUTOMAKE_VERSION -# ------------------------------- -# Call AM_AUTOMAKE_VERSION so it can be traced. -# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. -AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], - [AM_AUTOMAKE_VERSION([1.9.6])]) - -# AM_AUX_DIR_EXPAND -*- Autoconf -*- - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. -# -# Of course, Automake must honor this variable whenever it calls a -# tool from the auxiliary directory. The problem is that $srcdir (and -# therefore $ac_aux_dir as well) can be either absolute or relative, -# depending on how configure is run. This is pretty annoying, since -# it makes $ac_aux_dir quite unusable in subdirectories: in the top -# source directory, any form will work fine, but in subdirectories a -# relative path needs to be adjusted first. -# -# $ac_aux_dir/missing -# fails when called from a subdirectory if $ac_aux_dir is relative -# $top_srcdir/$ac_aux_dir/missing -# fails if $ac_aux_dir is absolute, -# fails when called from a subdirectory in a VPATH build with -# a relative $ac_aux_dir -# -# The reason of the latter failure is that $top_srcdir and $ac_aux_dir -# are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you -# start a VPATH build or use an absolute $srcdir. -# -# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, -# iff we strip the leading $srcdir from $ac_aux_dir. That would be: -# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` -# and then we would define $MISSING as -# MISSING="\${SHELL} $am_aux_dir/missing" -# This will work as long as MISSING is not called from configure, because -# unfortunately $(top_srcdir) has no meaning in configure. -# However there are other variables, like CC, which are often used in -# configure, and could therefore not use this "fixed" $ac_aux_dir. -# -# Another solution, used here, is to always expand $ac_aux_dir to an -# absolute PATH. The drawback is that using absolute paths prevent a -# configured tree to be moved without reconfiguration. - -AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` -]) - -# AM_CONDITIONAL -*- Autoconf -*- - -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 7 - -# AM_CONDITIONAL(NAME, SHELL-CONDITION) -# ------------------------------------- -# Define a conditional. -AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl -AC_SUBST([$1_TRUE]) -AC_SUBST([$1_FALSE]) -if $2; then - $1_TRUE= - $1_FALSE='#' -else - $1_TRUE='#' - $1_FALSE= -fi -AC_CONFIG_COMMANDS_PRE( -[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then - AC_MSG_ERROR([[conditional "$1" was never defined. -Usually this means the macro was only invoked conditionally.]]) -fi])]) - - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be -# written in clear, in which case automake, when reading aclocal.m4, -# will think it sees a *use*, and therefore will trigger all it's -# C support machinery. Also note that it means that autoscan, seeing -# CC etc. in the Makefile, will ask for an AC_PROG_CC use... - - -# _AM_DEPENDENCIES(NAME) -# ---------------------- -# See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". -# We try a few techniques and use that to set a single cache variable. -# -# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was -# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular -# dependency, and given that the user is not expected to run this macro, -# just rely on AC_PROG_CC. -AC_DEFUN([_AM_DEPENDENCIES], -[AC_REQUIRE([AM_SET_DEPDIR])dnl -AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl -AC_REQUIRE([AM_MAKE_INCLUDE])dnl -AC_REQUIRE([AM_DEP_TRACK])dnl - -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) - -AC_CACHE_CHECK([dependency style of $depcc], - [am_cv_$1_dependencies_compiler_type], -[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_$1_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_$1_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_$1_dependencies_compiler_type=none -fi -]) -AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) -AM_CONDITIONAL([am__fastdep$1], [ - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) -]) - - -# AM_SET_DEPDIR -# ------------- -# Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES -AC_DEFUN([AM_SET_DEPDIR], -[AC_REQUIRE([AM_SET_LEADING_DOT])dnl -AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl -]) - - -# AM_DEP_TRACK -# ------------ -AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi -AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) -AC_SUBST([AMDEPBACKSLASH]) -]) - -# Generate code to set up dependency tracking. -*- Autoconf -*- - -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -#serial 3 - -# _AM_OUTPUT_DEPENDENCY_COMMANDS -# ------------------------------ -AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], -[for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done -done -])# _AM_OUTPUT_DEPENDENCY_COMMANDS - - -# AM_OUTPUT_DEPENDENCY_COMMANDS -# ----------------------------- -# This macro should only be invoked once -- use via AC_REQUIRE. -# -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. -AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], -[AC_CONFIG_COMMANDS([depfiles], - [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Do all the work for Automake. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 12 - -# This macro actually does too much. Some checks are only needed if -# your package does certain things. But this isn't really a big deal. - -# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) -# AM_INIT_AUTOMAKE([OPTIONS]) -# ----------------------------------------------- -# The call with PACKAGE and VERSION arguments is the old style -# call (pre autoconf-2.50), which is being phased out. PACKAGE -# and VERSION should now be passed to AC_INIT and removed from -# the call to AM_INIT_AUTOMAKE. -# We support both call styles for the transition. After -# the next Automake release, Autoconf can make the AC_INIT -# arguments mandatory, and then we can depend on a new Autoconf -# release and drop the old call support. -AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.58])dnl -dnl Autoconf wants to disallow AM_ names. We explicitly allow -dnl the ones we care about. -m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl -AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl -AC_REQUIRE([AC_PROG_INSTALL])dnl -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi -AC_SUBST([CYGPATH_W]) - -# Define the identity of the package. -dnl Distinguish between old-style and new-style calls. -m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl - AC_SUBST([PACKAGE], [$1])dnl - AC_SUBST([VERSION], [$2])], -[_AM_SET_OPTIONS([$1])dnl - AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl - AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl - -_AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl - -# Some tools Automake needs. -AC_REQUIRE([AM_SANITY_CHECK])dnl -AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) -AM_PROG_INSTALL_SH -AM_PROG_INSTALL_STRIP -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -AC_REQUIRE([AC_PROG_AWK])dnl -AC_REQUIRE([AC_PROG_MAKE_SET])dnl -AC_REQUIRE([AM_SET_LEADING_DOT])dnl -_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], - [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], - [_AM_PROG_TAR([v7])])]) -_AM_IF_OPTION([no-dependencies],, -[AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl -AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl -]) -]) - - -# When config.status generates a header, we must update the stamp-h file. -# This file resides in the same directory as the config header -# that is generated. The stamp files are numbered to have different names. - -# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the -# loop where config.status creates the headers, so we can generate -# our stamp files there. -AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], -[# Compute $1's index in $config_headers. -_am_stamp_count=1 -for _am_header in $config_headers :; do - case $_am_header in - $1 | $1:* ) - break ;; - * ) - _am_stamp_count=`expr $_am_stamp_count + 1` ;; - esac -done -echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_SH -# ------------------ -# Define $install_sh. -AC_DEFUN([AM_PROG_INSTALL_SH], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -install_sh=${install_sh-"$am_aux_dir/install-sh"} -AC_SUBST(install_sh)]) - -# Copyright (C) 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# Check whether the underlying file-system supports filenames -# with a leading dot. For instance MS-DOS doesn't. -AC_DEFUN([AM_SET_LEADING_DOT], -[rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null -AC_SUBST([am__leading_dot])]) - -# Check to see how 'make' treats includes. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 3 - -# AM_MAKE_INCLUDE() -# ----------------- -# Check to see how make treats includes. -AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo done -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) - -# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- - -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# AM_MISSING_PROG(NAME, PROGRAM) -# ------------------------------ -AC_DEFUN([AM_MISSING_PROG], -[AC_REQUIRE([AM_MISSING_HAS_RUN]) -$1=${$1-"${am_missing_run}$2"} -AC_SUBST($1)]) - - -# AM_MISSING_HAS_RUN -# ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. -AC_DEFUN([AM_MISSING_HAS_RUN], -[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) -fi -]) - -# Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_MKDIR_P -# --------------- -# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise. -# -# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories -# created by `make install' are always world readable, even if the -# installer happens to have an overly restrictive umask (e.g. 077). -# This was a mistake. There are at least two reasons why we must not -# use `-m 0755': -# - it causes special bits like SGID to be ignored, -# - it may be too restrictive (some setups expect 775 directories). -# -# Do not use -m 0755 and let people choose whatever they expect by -# setting umask. -# -# We cannot accept any implementation of `mkdir' that recognizes `-p'. -# Some implementations (such as Solaris 8's) are not thread-safe: if a -# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c' -# concurrently, both version can detect that a/ is missing, but only -# one can create it and the other will error out. Consequently we -# restrict ourselves to GNU make (using the --version option ensures -# this.) -AC_DEFUN([AM_PROG_MKDIR_P], -[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - # We used to keeping the `.' as first argument, in order to - # allow $(mkdir_p) to be used without argument. As in - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. However this is wrong - # for two reasons: - # 1. if the package is installed by a user who cannot write `.' - # make install will fail, - # 2. the above comment should most certainly read - # $(mkdir_p) $(DESTDIR)$(somedir) - # so it does not work when $(somedir) is undefined and - # $(DESTDIR) is not. - # To support the latter case, we have to write - # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), - # so the `.' trick is pointless. - mkdir_p='mkdir -p --' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--version; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' - else - mkdir_p='$(install_sh) -d' - fi -fi -AC_SUBST([mkdir_p])]) - -# Helper functions for option handling. -*- Autoconf -*- - -# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 3 - -# _AM_MANGLE_OPTION(NAME) -# ----------------------- -AC_DEFUN([_AM_MANGLE_OPTION], -[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) - -# _AM_SET_OPTION(NAME) -# ------------------------------ -# Set option NAME. Presently that only means defining a flag for this option. -AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) - -# _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- -# OPTIONS is a space-separated list of Automake options. -AC_DEFUN([_AM_SET_OPTIONS], -[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) - -# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) -# ------------------------------------------- -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -AC_DEFUN([_AM_IF_OPTION], -[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) - -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# AM_SANITY_CHECK -# --------------- -AC_DEFUN([AM_SANITY_CHECK], -[AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi - - test "$[2]" = conftest.file - ) -then - # Ok. - : -else - AC_MSG_ERROR([newly created file is older than distributed files! -Check your system clock]) -fi -AC_MSG_RESULT(yes)]) - -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_INSTALL_STRIP -# --------------------- -# One issue with vendor `install' (even GNU) is that you can't -# specify the program used to strip binaries. This is especially -# annoying in cross-compiling environments, where the build's strip -# is unlikely to handle the host's binaries. -# Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize -# STRIPPROG with the value of the STRIP variable (set by the user). -AC_DEFUN([AM_PROG_INSTALL_STRIP], -[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. -if test "$cross_compiling" != no; then - AC_CHECK_TOOL([STRIP], [strip], :) -fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" -AC_SUBST([INSTALL_STRIP_PROGRAM])]) - -# Check how to create a tarball. -*- Autoconf -*- - -# Copyright (C) 2004, 2005 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 2 - -# _AM_PROG_TAR(FORMAT) -# -------------------- -# Check how to create a tarball in format FORMAT. -# FORMAT should be one of `v7', `ustar', or `pax'. -# -# Substitute a variable $(am__tar) that is a command -# writing to stdout a FORMAT-tarball containing the directory -# $tardir. -# tardir=directory && $(am__tar) > result.tar -# -# Substitute a variable $(am__untar) that extract such -# a tarball read from stdin. -# $(am__untar) < result.tar -AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. -AM_MISSING_PROG([AMTAR], [tar]) -m4_if([$1], [v7], - [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of `-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break - - # tar/untar a dummy directory, and stop if the command works - rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir - -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) -AC_SUBST([am__tar]) -AC_SUBST([am__untar]) -]) # _AM_PROG_TAR - diff --git a/src/sound/resid-fp/array.h b/src/sound/resid-fp/array.h new file mode 100644 index 0000000000..a0d3909662 --- /dev/null +++ b/src/sound/resid-fp/array.h @@ -0,0 +1,86 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright (C) 2011-2014 Leandro Nini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ARRAY_H +#define ARRAY_H + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_CXX11 +# include +#endif + +/** + * Counter. + */ +class counter +{ +private: +#ifndef HAVE_CXX11 + volatile unsigned int c; +#else + std::atomic c; +#endif + +public: + counter() : c(1) {} + void increase() { ++c; } + unsigned int decrease() { return --c; } +}; + +/** + * Reference counted pointer to matrix wrapper, for use with standard containers. + */ +template +class matrix +{ +private: + T* data; + counter* count; + const unsigned int x, y; + +public: + matrix(unsigned int x, unsigned int y) : + data(new T[x * y]), + count(new counter()), + x(x), + y(y) {} + + matrix(const matrix& p) : + data(p.data), + count(p.count), + x(p.x), + y(p.y) { count->increase(); } + + ~matrix() { if (count->decrease() == 0) { delete count; delete [] data; } } + + unsigned int length() const { return x * y; } + + T* operator[](unsigned int a) { return &data[a * y]; } + + T const* operator[](unsigned int a) const { return &data[a * y]; } +}; + +typedef matrix matrix_t; + +#endif diff --git a/src/sound/resid-fp/config.h b/src/sound/resid-fp/config.h new file mode 100644 index 0000000000..0eeba8dee8 --- /dev/null +++ b/src/sound/resid-fp/config.h @@ -0,0 +1 @@ +#define HAVE_CXX14 diff --git a/src/sound/resid-fp/configure b/src/sound/resid-fp/configure deleted file mode 100644 index 35a9c8f7d0..0000000000 --- a/src/sound/resid-fp/configure +++ /dev/null @@ -1,5955 +0,0 @@ -#! /bin/sh -# Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61. -# -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# This configure script is free software; the Free Software Foundation -# gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -as_nl=' -' -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } -fi - -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# CDPATH. -$as_unset CDPATH - - -if test "x$CONFIG_SHELL" = x; then - if (eval ":") 2>/dev/null; then - as_have_required=yes -else - as_have_required=no -fi - - if test $as_have_required = yes && (eval ": -(as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=\$LINENO - as_lineno_2=\$LINENO - test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && - test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } -") 2> /dev/null; then - : -else - as_candidate_shells= - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - case $as_dir in - /*) - for as_base in sh bash ksh sh5; do - as_candidate_shells="$as_candidate_shells $as_dir/$as_base" - done;; - esac -done -IFS=$as_save_IFS - - - for as_shell in $as_candidate_shells $SHELL; do - # Try only shells that exist, to save several forks. - if { test -f "$as_shell" || test -f "$as_shell.exe"; } && - { ("$as_shell") 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -_ASEOF -}; then - CONFIG_SHELL=$as_shell - as_have_required=yes - if { "$as_shell" 2> /dev/null <<\_ASEOF -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - -: -(as_func_return () { - (exit $1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = "$1" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test $exitcode = 0) || { (exit 1); exit 1; } - -( - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } - -_ASEOF -}; then - break -fi - -fi - - done - - if test "x$CONFIG_SHELL" != x; then - for as_var in BASH_ENV ENV - do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - done - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} -fi - - - if test $as_have_required = no; then - echo This script requires a shell more modern than all the - echo shells that I found on your system. Please install a - echo modern shell, or manually run the script under such a - echo shell if you do have one. - { (exit 1); exit 1; } -fi - - -fi - -fi - - - -(eval "as_func_return () { - (exit \$1) -} -as_func_success () { - as_func_return 0 -} -as_func_failure () { - as_func_return 1 -} -as_func_ret_success () { - return 0 -} -as_func_ret_failure () { - return 1 -} - -exitcode=0 -if as_func_success; then - : -else - exitcode=1 - echo as_func_success failed. -fi - -if as_func_failure; then - exitcode=1 - echo as_func_failure succeeded. -fi - -if as_func_ret_success; then - : -else - exitcode=1 - echo as_func_ret_success failed. -fi - -if as_func_ret_failure; then - exitcode=1 - echo as_func_ret_failure succeeded. -fi - -if ( set x; as_func_ret_success y && test x = \"\$1\" ); then - : -else - exitcode=1 - echo positional parameters were not saved. -fi - -test \$exitcode = 0") || { - echo No shell found that supports shell functions. - echo Please tell autoconf@gnu.org about your system, - echo including any error possibly output before this - echo message -} - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in --n*) - case `echo 'x\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; - esac;; -*) - ECHO_N='-n';; -esac - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir -fi -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - - -exec 7<&0 &1 - -# Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, -# so uname gets run too. -ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` - -# -# Initializations. -# -ac_default_prefix=/usr/local -ac_clean_files= -ac_config_libobj_dir=. -LIBOBJS= -cross_compiling=no -subdirs= -MFLAGS= -MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Identity of this package. -PACKAGE_NAME= -PACKAGE_TARNAME= -PACKAGE_VERSION= -PACKAGE_STRING= -PACKAGE_BUGREPORT= - -ac_unique_file="sid.h" -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='SHELL -PATH_SEPARATOR -PACKAGE_NAME -PACKAGE_TARNAME -PACKAGE_VERSION -PACKAGE_STRING -PACKAGE_BUGREPORT -exec_prefix -prefix -program_transform_name -bindir -sbindir -libexecdir -datarootdir -datadir -sysconfdir -sharedstatedir -localstatedir -includedir -oldincludedir -docdir -infodir -htmldir -dvidir -pdfdir -psdir -libdir -localedir -mandir -DEFS -ECHO_C -ECHO_N -ECHO_T -LIBS -build_alias -host_alias -target_alias -INSTALL_PROGRAM -INSTALL_SCRIPT -INSTALL_DATA -CYGPATH_W -PACKAGE -VERSION -ACLOCAL -AUTOCONF -AUTOMAKE -AUTOHEADER -MAKEINFO -install_sh -STRIP -INSTALL_STRIP_PROGRAM -mkdir_p -AWK -SET_MAKE -am__leading_dot -AMTAR -am__tar -am__untar -RESID_INLINE -CXX -CXXFLAGS -LDFLAGS -CPPFLAGS -ac_ct_CXX -EXEEXT -OBJEXT -DEPDIR -am__include -am__quote -AMDEP_TRUE -AMDEP_FALSE -AMDEPBACKSLASH -CXXDEPMODE -am__fastdepCXX_TRUE -am__fastdepCXX_FALSE -AR -RANLIB -PERL -CXXCPP -GREP -EGREP -USE_SSE_TRUE -USE_SSE_FALSE -RESID_HAVE_BOOL -RESID_USE_SSE -HAVE_LOGF_PROTOTYPE -HAVE_EXPF_PROTOTYPE -LIBOBJS -LTLIBOBJS' -ac_subst_files='' - ac_precious_vars='build_alias -host_alias -target_alias -CXX -CXXFLAGS -LDFLAGS -LIBS -CPPFLAGS -CCC -CXXCPP' - - -# Initialize some variables set by options. -ac_init_help= -ac_init_version=false -# The variables have the same names as the options, with -# dashes changed to underlines. -cache_file=/dev/null -exec_prefix=NONE -no_create= -no_recursion= -prefix=NONE -program_prefix=NONE -program_suffix=NONE -program_transform_name=s,x,x, -silent= -site= -srcdir= -verbose= -x_includes=NONE -x_libraries=NONE - -# Installation directory options. -# These are left unexpanded so users can "make install exec_prefix=/foo" -# and all the variables that are supposed to be based on exec_prefix -# by default will actually change. -# Use braces instead of parens because sh, perl, etc. also accept them. -# (The list follows the same order as the GNU Coding Standards.) -bindir='${exec_prefix}/bin' -sbindir='${exec_prefix}/sbin' -libexecdir='${exec_prefix}/libexec' -datarootdir='${prefix}/share' -datadir='${datarootdir}' -sysconfdir='${prefix}/etc' -sharedstatedir='${prefix}/com' -localstatedir='${prefix}/var' -includedir='${prefix}/include' -oldincludedir='/usr/include' -docdir='${datarootdir}/doc/${PACKAGE}' -infodir='${datarootdir}/info' -htmldir='${docdir}' -dvidir='${docdir}' -pdfdir='${docdir}' -psdir='${docdir}' -libdir='${exec_prefix}/lib' -localedir='${datarootdir}/locale' -mandir='${datarootdir}/man' - -ac_prev= -ac_dashdash= -for ac_option -do - # If the previous option needs an argument, assign it. - if test -n "$ac_prev"; then - eval $ac_prev=\$ac_option - ac_prev= - continue - fi - - case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; - esac - - # Accept the important Cygnus configure options, so we can diagnose typos. - - case $ac_dashdash$ac_option in - --) - ac_dashdash=yes ;; - - -bindir | --bindir | --bindi | --bind | --bin | --bi) - ac_prev=bindir ;; - -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) - bindir=$ac_optarg ;; - - -build | --build | --buil | --bui | --bu) - ac_prev=build_alias ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=*) - build_alias=$ac_optarg ;; - - -cache-file | --cache-file | --cache-fil | --cache-fi \ - | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) - ac_prev=cache_file ;; - -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ - | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) - cache_file=$ac_optarg ;; - - --config-cache | -C) - cache_file=config.cache ;; - - -datadir | --datadir | --datadi | --datad) - ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=*) - datadir=$ac_optarg ;; - - -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ - | --dataroo | --dataro | --datar) - ac_prev=datarootdir ;; - -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ - | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) - datarootdir=$ac_optarg ;; - - -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` - eval enable_$ac_feature=no ;; - - -docdir | --docdir | --docdi | --doc | --do) - ac_prev=docdir ;; - -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) - docdir=$ac_optarg ;; - - -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) - ac_prev=dvidir ;; - -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) - dvidir=$ac_optarg ;; - - -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/[-.]/_/g'` - eval enable_$ac_feature=\$ac_optarg ;; - - -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ - | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ - | --exec | --exe | --ex) - ac_prev=exec_prefix ;; - -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ - | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ - | --exec=* | --exe=* | --ex=*) - exec_prefix=$ac_optarg ;; - - -gas | --gas | --ga | --g) - # Obsolete; use --with-gas. - with_gas=yes ;; - - -help | --help | --hel | --he | -h) - ac_init_help=long ;; - -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) - ac_init_help=recursive ;; - -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) - ac_init_help=short ;; - - -host | --host | --hos | --ho) - ac_prev=host_alias ;; - -host=* | --host=* | --hos=* | --ho=*) - host_alias=$ac_optarg ;; - - -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) - ac_prev=htmldir ;; - -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ - | --ht=*) - htmldir=$ac_optarg ;; - - -includedir | --includedir | --includedi | --included | --include \ - | --includ | --inclu | --incl | --inc) - ac_prev=includedir ;; - -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ - | --includ=* | --inclu=* | --incl=* | --inc=*) - includedir=$ac_optarg ;; - - -infodir | --infodir | --infodi | --infod | --info | --inf) - ac_prev=infodir ;; - -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) - infodir=$ac_optarg ;; - - -libdir | --libdir | --libdi | --libd) - ac_prev=libdir ;; - -libdir=* | --libdir=* | --libdi=* | --libd=*) - libdir=$ac_optarg ;; - - -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ - | --libexe | --libex | --libe) - ac_prev=libexecdir ;; - -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ - | --libexe=* | --libex=* | --libe=*) - libexecdir=$ac_optarg ;; - - -localedir | --localedir | --localedi | --localed | --locale) - ac_prev=localedir ;; - -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) - localedir=$ac_optarg ;; - - -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst | --locals) - ac_prev=localstatedir ;; - -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) - localstatedir=$ac_optarg ;; - - -mandir | --mandir | --mandi | --mand | --man | --ma | --m) - ac_prev=mandir ;; - -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) - mandir=$ac_optarg ;; - - -nfp | --nfp | --nf) - # Obsolete; use --without-fp. - with_fp=no ;; - - -no-create | --no-create | --no-creat | --no-crea | --no-cre \ - | --no-cr | --no-c | -n) - no_create=yes ;; - - -no-recursion | --no-recursion | --no-recursio | --no-recursi \ - | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) - no_recursion=yes ;; - - -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ - | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ - | --oldin | --oldi | --old | --ol | --o) - ac_prev=oldincludedir ;; - -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ - | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ - | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) - oldincludedir=$ac_optarg ;; - - -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) - ac_prev=prefix ;; - -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) - prefix=$ac_optarg ;; - - -program-prefix | --program-prefix | --program-prefi | --program-pref \ - | --program-pre | --program-pr | --program-p) - ac_prev=program_prefix ;; - -program-prefix=* | --program-prefix=* | --program-prefi=* \ - | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) - program_prefix=$ac_optarg ;; - - -program-suffix | --program-suffix | --program-suffi | --program-suff \ - | --program-suf | --program-su | --program-s) - ac_prev=program_suffix ;; - -program-suffix=* | --program-suffix=* | --program-suffi=* \ - | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) - program_suffix=$ac_optarg ;; - - -program-transform-name | --program-transform-name \ - | --program-transform-nam | --program-transform-na \ - | --program-transform-n | --program-transform- \ - | --program-transform | --program-transfor \ - | --program-transfo | --program-transf \ - | --program-trans | --program-tran \ - | --progr-tra | --program-tr | --program-t) - ac_prev=program_transform_name ;; - -program-transform-name=* | --program-transform-name=* \ - | --program-transform-nam=* | --program-transform-na=* \ - | --program-transform-n=* | --program-transform-=* \ - | --program-transform=* | --program-transfor=* \ - | --program-transfo=* | --program-transf=* \ - | --program-trans=* | --program-tran=* \ - | --progr-tra=* | --program-tr=* | --program-t=*) - program_transform_name=$ac_optarg ;; - - -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) - ac_prev=pdfdir ;; - -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) - pdfdir=$ac_optarg ;; - - -psdir | --psdir | --psdi | --psd | --ps) - ac_prev=psdir ;; - -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) - psdir=$ac_optarg ;; - - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - silent=yes ;; - - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) - ac_prev=sbindir ;; - -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ - | --sbi=* | --sb=*) - sbindir=$ac_optarg ;; - - -sharedstatedir | --sharedstatedir | --sharedstatedi \ - | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ - | --sharedst | --shareds | --shared | --share | --shar \ - | --sha | --sh) - ac_prev=sharedstatedir ;; - -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ - | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ - | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ - | --sha=* | --sh=*) - sharedstatedir=$ac_optarg ;; - - -site | --site | --sit) - ac_prev=site ;; - -site=* | --site=* | --sit=*) - site=$ac_optarg ;; - - -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) - ac_prev=srcdir ;; - -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) - srcdir=$ac_optarg ;; - - -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ - | --syscon | --sysco | --sysc | --sys | --sy) - ac_prev=sysconfdir ;; - -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ - | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) - sysconfdir=$ac_optarg ;; - - -target | --target | --targe | --targ | --tar | --ta | --t) - ac_prev=target_alias ;; - -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) - target_alias=$ac_optarg ;; - - -v | -verbose | --verbose | --verbos | --verbo | --verb) - verbose=yes ;; - - -version | --version | --versio | --versi | --vers | -V) - ac_init_version=: ;; - - -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/[-.]/_/g'` - eval with_$ac_package=\$ac_optarg ;; - - -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` - # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-._$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/[-.]/_/g'` - eval with_$ac_package=no ;; - - --x) - # Obsolete; use --with-x. - with_x=yes ;; - - -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ - | --x-incl | --x-inc | --x-in | --x-i) - ac_prev=x_includes ;; - -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ - | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) - x_includes=$ac_optarg ;; - - -x-libraries | --x-libraries | --x-librarie | --x-librari \ - | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) - ac_prev=x_libraries ;; - -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ - | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) - x_libraries=$ac_optarg ;; - - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } - ;; - - *=*) - ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` - # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - eval $ac_envvar=\$ac_optarg - export $ac_envvar ;; - - *) - # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} - ;; - - esac -done - -if test -n "$ac_prev"; then - ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } -fi - -# Be sure to have absolute directory names. -for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ - datadir sysconfdir sharedstatedir localstatedir includedir \ - oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir -do - eval ac_val=\$$ac_var - case $ac_val in - [\\/$]* | ?:[\\/]* ) continue;; - NONE | '' ) case $ac_var in *prefix ) continue;; esac;; - esac - { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; } -done - -# There might be people who depend on the old broken behavior: `$host' -# used to hold the argument of --host etc. -# FIXME: To remove some day. -build=$build_alias -host=$host_alias -target=$target_alias - -# FIXME: To remove some day. -if test "x$host_alias" != x; then - if test "x$build_alias" = x; then - cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 - elif test "x$build_alias" != "x$host_alias"; then - cross_compiling=yes - fi -fi - -ac_tool_prefix= -test -n "$host_alias" && ac_tool_prefix=$host_alias- - -test "$silent" = yes && exec 6>/dev/null - - -ac_pwd=`pwd` && test -n "$ac_pwd" && -ac_ls_di=`ls -di .` && -ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - { echo "$as_me: error: Working directory cannot be determined" >&2 - { (exit 1); exit 1; }; } -test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - { echo "$as_me: error: pwd does not report name of working directory" >&2 - { (exit 1); exit 1; }; } - - -# Find the source files, if location was not specified. -if test -z "$srcdir"; then - ac_srcdir_defaulted=yes - # Try the directory containing this script, then the parent directory. - ac_confdir=`$as_dirname -- "$0" || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - srcdir=$ac_confdir - if test ! -r "$srcdir/$ac_unique_file"; then - srcdir=.. - fi -else - ac_srcdir_defaulted=no -fi -if test ! -r "$srcdir/$ac_unique_file"; then - test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } -fi -ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" -ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2 - { (exit 1); exit 1; }; } - pwd)` -# When building in place, set srcdir=. -if test "$ac_abs_confdir" = "$ac_pwd"; then - srcdir=. -fi -# Remove unnecessary trailing slashes from srcdir. -# Double slashes in file names in object file debugging info -# mess up M-x gdb in Emacs. -case $srcdir in -*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; -esac -for ac_var in $ac_precious_vars; do - eval ac_env_${ac_var}_set=\${${ac_var}+set} - eval ac_env_${ac_var}_value=\$${ac_var} - eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} - eval ac_cv_env_${ac_var}_value=\$${ac_var} -done - -# -# Report the --help message. -# -if test "$ac_init_help" = "long"; then - # Omit some internal or obsolete options to make the list less imposing. - # This message is too long to be a string in the A/UX 3.1 sh. - cat <<_ACEOF -\`configure' configures this package to adapt to many kinds of systems. - -Usage: $0 [OPTION]... [VAR=VALUE]... - -To assign environment variables (e.g., CC, CFLAGS...), specify them as -VAR=VALUE. See below for descriptions of some of the useful variables. - -Defaults for the options are specified in brackets. - -Configuration: - -h, --help display this help and exit - --help=short display options specific to this package - --help=recursive display the short help of all the included packages - -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages - --cache-file=FILE cache test results in FILE [disabled] - -C, --config-cache alias for \`--cache-file=config.cache' - -n, --no-create do not create output files - --srcdir=DIR find the sources in DIR [configure dir or \`..'] - -Installation directories: - --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] - --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] - -By default, \`make install' will install all the files in -\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify -an installation prefix other than \`$ac_default_prefix' using \`--prefix', -for instance \`--prefix=\$HOME'. - -For better control, use the options below. - -Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -_ACEOF - - cat <<\_ACEOF - -Program names: - --program-prefix=PREFIX prepend PREFIX to installed program names - --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names -_ACEOF -fi - -if test -n "$ac_init_help"; then - - cat <<\_ACEOF - -Optional Features: - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-inline enable inlining of functions default=yes - --enable-sse enable the use of SSE default=yes - --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors - -Some influential environment variables: - CXX C++ compiler command - CXXFLAGS C++ compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - LIBS libraries to pass to the linker, e.g. -l - CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if - you have headers in a nonstandard directory - CXXCPP C++ preprocessor - -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - -_ACEOF -ac_status=$? -fi - -if test "$ac_init_help" = "recursive"; then - # If there are subdirs, report their specific --help. - for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d "$ac_dir" || continue - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - cd "$ac_dir" || { ac_status=$?; continue; } - # Check for guested configure. - if test -f "$ac_srcdir/configure.gnu"; then - echo && - $SHELL "$ac_srcdir/configure.gnu" --help=recursive - elif test -f "$ac_srcdir/configure"; then - echo && - $SHELL "$ac_srcdir/configure" --help=recursive - else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi || ac_status=$? - cd "$ac_pwd" || { ac_status=$?; break; } - done -fi - -test -n "$ac_init_help" && exit $ac_status -if $ac_init_version; then - cat <<\_ACEOF -configure -generated by GNU Autoconf 2.61 - -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -This configure script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it. -_ACEOF - exit -fi -cat >config.log <<_ACEOF -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by $as_me, which was -generated by GNU Autoconf 2.61. Invocation command line was - - $ $0 $@ - -_ACEOF -exec 5>>config.log -{ -cat <<_ASUNAME -## --------- ## -## Platform. ## -## --------- ## - -hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` -uname -m = `(uname -m) 2>/dev/null || echo unknown` -uname -r = `(uname -r) 2>/dev/null || echo unknown` -uname -s = `(uname -s) 2>/dev/null || echo unknown` -uname -v = `(uname -v) 2>/dev/null || echo unknown` - -/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` -/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` - -/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` -/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` -/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` -/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` -/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` -/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` - -_ASUNAME - -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done -IFS=$as_save_IFS - -} >&5 - -cat >&5 <<_ACEOF - - -## ----------- ## -## Core tests. ## -## ----------- ## - -_ACEOF - - -# Keep a trace of the command line. -# Strip out --no-create and --no-recursion so they do not pile up. -# Strip out --silent because we don't want to record it for future runs. -# Also quote any args containing shell meta-characters. -# Make two passes to allow for proper duplicate-argument suppression. -ac_configure_args= -ac_configure_args0= -ac_configure_args1= -ac_must_keep_next=false -for ac_pass in 1 2 -do - for ac_arg - do - case $ac_arg in - -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil) - continue ;; - *\'*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; - esac - case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; - 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" - if test $ac_must_keep_next = true; then - ac_must_keep_next=false # Got value, back to normal. - else - case $ac_arg in - *=* | --config-cache | -C | -disable-* | --disable-* \ - | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ - | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ - | -with-* | --with-* | -without-* | --without-* | --x) - case "$ac_configure_args0 " in - "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; - esac - ;; - -* ) ac_must_keep_next=true ;; - esac - fi - ac_configure_args="$ac_configure_args '$ac_arg'" - ;; - esac - done -done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } - -# When interrupted or exit'd, cleanup temporary files, and complete -# config.log. We remove comments because anyway the quotes in there -# would cause problems or look ugly. -# WARNING: Use '\'' to represent an apostrophe within the trap. -# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. -trap 'exit_status=$? - # Save into config.log some information that might help in debugging. - { - echo - - cat <<\_ASBOX -## ---------------- ## -## Cache variables. ## -## ---------------- ## -_ASBOX - echo - # The following way of writing the cache mishandles newlines in values, -( - for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - (set) 2>&1 | - case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - sed -n \ - "s/'\''/'\''\\\\'\'''\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" - ;; #( - *) - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) - echo - - cat <<\_ASBOX -## ----------------- ## -## Output variables. ## -## ----------------- ## -_ASBOX - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## -## File substitutions. ## -## ------------------- ## -_ASBOX - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## -## confdefs.h. ## -## ----------- ## -_ASBOX - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" - } >&5 - rm -f core *.core core.conftest.* && - rm -f -r conftest* confdefs* conf$$* $ac_clean_files && - exit $exit_status -' 0 -for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal -done -ac_signal=0 - -# confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -f -r conftest* confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -n "$CONFIG_SITE"; then - set x "$CONFIG_SITE" -elif test "x$prefix" != xNONE; then - set x "$prefix/share/config.site" "$prefix/etc/config.site" -else - set x "$ac_default_prefix/share/config.site" \ - "$ac_default_prefix/etc/config.site" -fi -shift -for ac_site_file -do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" - fi -done - -if test -r "$cache_file"; then - # Some versions of bash will fail to source /dev/null (special - # files actually), so we avoid doing that. - if test -f "$cache_file"; then - { echo "$as_me:$LINENO: loading cache $cache_file" >&5 -echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { echo "$as_me:$LINENO: creating cache $cache_file" >&5 -echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# Check that the precious variables saved in the cache have kept the same -# value. -ac_cache_corrupted=false -for ac_var in $ac_precious_vars; do - eval ac_old_set=\$ac_cv_env_${ac_var}_set - eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val=\$ac_cv_env_${ac_var}_value - eval ac_new_val=\$ac_env_${ac_var}_value - case $ac_old_set,$ac_new_set in - set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,);; - *) - if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: - fi;; - esac - # Pass precious variables to config.status. - if test "$ac_new_set" = set; then - case $ac_new_val in - *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; - *) ac_arg=$ac_var=$ac_new_val ;; - esac - case " $ac_configure_args " in - *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; - esac - fi -done -if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } -fi - - - - - - - - - - - - - - - - - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - -am__api_version="1.9" -ac_aux_dir= -for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 -echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} - { (exit 1); exit 1; }; } -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - -# Find a good install program. We prefer a C program (faster), -# so one script is as good as another. But avoid the broken or -# incompatible versions: -# SysV /etc/install, /usr/sbin/install -# SunOS /usr/etc/install -# IRIX /sbin/install -# AIX /bin/install -# AmigaOS /C/install, which installs bootblocks on floppy discs -# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag -# AFS /usr/afsws/bin/install, which mishandles nonexistent args -# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" -# OS/2's system install, which has a completely different semantic -# ./install, which can be erroneously created by make from ./install.sh. -{ echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6; } -if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ - /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ - /usr/ucb/* ) ;; - *) - # OSF1 and SCO ODT 3.0 have their own names for install. - # Don't use installbsd from OSF since it installs stuff as root - # by default. - for ac_prog in ginstall scoinst install; do - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then - if test $ac_prog = install && - grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # AIX install. It has an incompatible calling convention. - : - elif test $ac_prog = install && - grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then - # program-specific install script used by HP pwplus--don't use. - : - else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 - fi - fi - done - done - ;; -esac -done -IFS=$as_save_IFS - - -fi - if test "${ac_cv_path_install+set}" = set; then - INSTALL=$ac_cv_path_install - else - # As a last resort, use the slow shell script. Don't cache a - # value for INSTALL within a source directory, because that will - # break other packages using the cache if that directory is - # removed, or if the value is a relative name. - INSTALL=$ac_install_sh - fi -fi -{ echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6; } - -# Use test -z because SunOS4 sh mishandles braces in ${var-val}. -# It thinks the first close brace ends the variable substitution. -test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' - -test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' - -test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' - -{ echo "$as_me:$LINENO: checking whether build environment is sane" >&5 -echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6; } -# Just in case -sleep 1 -echo timestamp > conftest.file -# Do `set' in a subshell so we don't clobber the current shell's -# arguments. Must try -L first in case configure is actually a -# symlink; some systems play weird games with the mod time of symlinks -# (eg FreeBSD returns the mod time of the symlink's containing -# directory). -if ( - set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t $srcdir/configure conftest.file` - fi - rm -f conftest.file - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&5 -echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken -alias in your environment" >&2;} - { (exit 1); exit 1; }; } - fi - - test "$2" = conftest.file - ) -then - # Ok. - : -else - { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! -Check your system clock" >&5 -echo "$as_me: error: newly created file is older than distributed files! -Check your system clock" >&2;} - { (exit 1); exit 1; }; } -fi -{ echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } -test "$program_prefix" != NONE && - program_transform_name="s&^&$program_prefix&;$program_transform_name" -# Use a double $ so make ignores it. -test "$program_suffix" != NONE && - program_transform_name="s&\$&$program_suffix&;$program_transform_name" -# Double any \ or $. echo might interpret backslashes. -# By default was `s,x,x', remove it if useless. -cat <<\_ACEOF >conftest.sed -s/[\\$]/&&/g;s/;s,x,x,$// -_ACEOF -program_transform_name=`echo $program_transform_name | sed -f conftest.sed` -rm -f conftest.sed - -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` - -test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" -# Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " -else - am_missing_run= - { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 -echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} -fi - -if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then - # We used to keeping the `.' as first argument, in order to - # allow $(mkdir_p) to be used without argument. As in - # $(mkdir_p) $(somedir) - # where $(somedir) is conditionally defined. However this is wrong - # for two reasons: - # 1. if the package is installed by a user who cannot write `.' - # make install will fail, - # 2. the above comment should most certainly read - # $(mkdir_p) $(DESTDIR)$(somedir) - # so it does not work when $(somedir) is undefined and - # $(DESTDIR) is not. - # To support the latter case, we have to write - # test -z "$(somedir)" || $(mkdir_p) $(DESTDIR)$(somedir), - # so the `.' trick is pointless. - mkdir_p='mkdir -p --' -else - # On NextStep and OpenStep, the `mkdir' command does not - # recognize any option. It will interpret all options as - # directories to create, and then abort because `.' already - # exists. - for d in ./-p ./--version; - do - test -d $d && rmdir $d - done - # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists. - if test -f "$ac_aux_dir/mkinstalldirs"; then - mkdir_p='$(mkinstalldirs)' - else - mkdir_p='$(install_sh) -d' - fi -fi - -for ac_prog in gawk mawk nawk awk -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AWK"; then - ac_cv_prog_AWK="$AWK" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AWK="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -AWK=$ac_cv_prog_AWK -if test -n "$AWK"; then - { echo "$as_me:$LINENO: result: $AWK" >&5 -echo "${ECHO_T}$AWK" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$AWK" && break -done - -{ echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6; } -set x ${MAKE-make}; ac_make=`echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.make <<\_ACEOF -SHELL = /bin/sh -all: - @echo '@@@%%%=$(MAKE)=@@@%%%' -_ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -case `${MAKE-make} -f conftest.make 2>/dev/null` in - *@@@%%%=?*=@@@%%%*) - eval ac_cv_prog_make_${ac_make}_set=yes;; - *) - eval ac_cv_prog_make_${ac_make}_set=no;; -esac -rm -f conftest.make -fi -if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - SET_MAKE= -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - SET_MAKE="MAKE=${MAKE-make}" -fi - -rm -rf .tst 2>/dev/null -mkdir .tst 2>/dev/null -if test -d .tst; then - am__leading_dot=. -else - am__leading_dot=_ -fi -rmdir .tst 2>/dev/null - -# test to see if srcdir already configured -if test "`cd $srcdir && pwd`" != "`pwd`" && - test -f $srcdir/config.status; then - { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 -echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} - { (exit 1); exit 1; }; } -fi - -# test whether we have cygpath -if test -z "$CYGPATH_W"; then - if (cygpath --version) >/dev/null 2>/dev/null; then - CYGPATH_W='cygpath -w' - else - CYGPATH_W=echo - fi -fi - - -# Define the identity of the package. - PACKAGE=resid - VERSION=0.16vice - - -cat >>confdefs.h <<_ACEOF -#define PACKAGE "$PACKAGE" -_ACEOF - - -cat >>confdefs.h <<_ACEOF -#define VERSION "$VERSION" -_ACEOF - -# Some tools Automake needs. - -ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} - - -AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} - - -AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} - - -AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} - - -MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} - -install_sh=${install_sh-"$am_aux_dir/install-sh"} - -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right -# tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -if test "$cross_compiling" != no; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. -set dummy ${ac_tool_prefix}strip; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$STRIP"; then - ac_cv_prog_STRIP="$STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_STRIP="${ac_tool_prefix}strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -STRIP=$ac_cv_prog_STRIP -if test -n "$STRIP"; then - { echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_STRIP"; then - ac_ct_STRIP=$STRIP - # Extract the first word of "strip", so it can be a program name with args. -set dummy strip; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_STRIP"; then - ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_STRIP="strip" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP -if test -n "$ac_ct_STRIP"; then - { echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 -echo "${ECHO_T}$ac_ct_STRIP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_STRIP" = x; then - STRIP=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - STRIP=$ac_ct_STRIP - fi -else - STRIP="$ac_cv_prog_STRIP" -fi - -fi -INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" - -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. - -AMTAR=${AMTAR-"${am_missing_run}tar"} - -am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' - - - - - -LTVERSION=5:0:0 - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -# Check whether --enable-inline was given. -if test "${enable_inline+set}" = set; then - enableval=$enable_inline; -fi - -# Check whether --enable-sse was given. -if test "${enable_sse+set}" = set; then - enableval=$enable_sse; -fi - - -if test "$enable_inline" != no; then - RESID_INLINE=inline -else - RESID_INLINE= -fi - - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -if test -z "$CXX"; then - if test -n "$CCC"; then - CXX=$CCC - else - if test -n "$ac_tool_prefix"; then - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$CXX"; then - ac_cv_prog_CXX="$CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -CXX=$ac_cv_prog_CXX -if test -n "$CXX"; then - { echo "$as_me:$LINENO: result: $CXX" >&5 -echo "${ECHO_T}$CXX" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$CXX" && break - done -fi -if test -z "$CXX"; then - ac_ct_CXX=$CXX - for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CXX"; then - ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_CXX="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_CXX=$ac_cv_prog_ac_ct_CXX -if test -n "$ac_ct_CXX"; then - { echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 -echo "${ECHO_T}$ac_ct_CXX" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$ac_ct_CXX" && break -done - - if test "x$ac_ct_CXX" = x; then - CXX="g++" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - CXX=$ac_ct_CXX - fi -fi - - fi -fi -# Provide some information about the compiler. -echo "$as_me:$LINENO: checking for C++ compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (ac_try="$ac_compiler --version >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler --version >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -v >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -v >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (ac_try="$ac_compiler -V >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compiler -V >&5") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" -# Try to create an executable without -o first, disregard a.out. -# It will help us diagnose broken compilers, and finding out an intuition -# of exeext. -{ echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5 -echo $ECHO_N "checking for C++ compiler default output file name... $ECHO_C" >&6; } -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -# -# List of possible output files, starting from the most likely. -# The algorithm is not robust to junk in `.', hence go to wildcards (a.*) -# only as a last resort. b.out is created by i960 compilers. -ac_files='a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out' -# -# The IRIX 6 linker writes into existing files which may not be -# executable, retaining their permissions. Remove them first so a -# subsequent execution test works. -ac_rmfiles= -for ac_file in $ac_files -do - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; - * ) ac_rmfiles="$ac_rmfiles $ac_file";; - esac -done -rm -f $ac_rmfiles - -if { (ac_try="$ac_link_default" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. -# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' -# in a Makefile. We should not override ac_cv_exeext if it was cached, -# so that the user can short-circuit this test for compilers unknown to -# Autoconf. -for ac_file in $ac_files '' -do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) - ;; - [ab].out ) - # We found the default executable, but exeext='' is most - # certainly right. - break;; - *.* ) - if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; - then :; else - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - fi - # We set ac_cv_exeext here because the later test for it is not - # safe: cross compilers may not add the suffix if given an `-o' - # argument, so we may need to know it at that point already. - # Even if this section looks crufty: it has the advantage of - # actually working. - break;; - * ) - break;; - esac -done -test "$ac_cv_exeext" = no && ac_cv_exeext= - -else - ac_file='' -fi - -{ echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6; } -if test -z "$ac_file"; then - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } -fi - -ac_exeext=$ac_cv_exeext - -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5 -echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6; } -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C++ compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -{ echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - -rm -f a.out a.exe conftest$ac_cv_exeext b.out -ac_clean_files=$ac_clean_files_save -# Check that the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -{ echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6; } -{ echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6; } - -{ echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6; } -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # If both `conftest.exe' and `conftest' are `present' (well, observable) -# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will -# work properly (i.e., refer to `conftest.exe'), while it won't with -# `rm'. -for ac_file in conftest.exe conftest conftest.*; do - test -f "$ac_file" || continue - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.o | *.obj ) ;; - *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - break;; - * ) break;; - esac -done -else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest$ac_cv_exeext -{ echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6; } - -rm -f conftest.$ac_ext -EXEEXT=$ac_cv_exeext -ac_exeext=$EXEEXT -{ echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6; } -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.o conftest.obj -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in conftest.o conftest.obj conftest.*; do - test -f "$ac_file" || continue; - case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf ) ;; - *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` - break;; - esac -done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -rm -f conftest.$ac_cv_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6; } -if test "${ac_cv_cxx_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_compiler_gnu=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_compiler_gnu=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_cxx_compiler_gnu=$ac_compiler_gnu - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6; } -GXX=`test $ac_compiler_gnu = yes && echo yes` -ac_test_CXXFLAGS=${CXXFLAGS+set} -ac_save_CXXFLAGS=$CXXFLAGS -{ echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 -echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6; } -if test "${ac_cv_prog_cxx_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_save_cxx_werror_flag=$ac_cxx_werror_flag - ac_cxx_werror_flag=yes - ac_cv_prog_cxx_g=no - CXXFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cxx_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - CXXFLAGS="" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cxx_werror_flag=$ac_save_cxx_werror_flag - CXXFLAGS="-g" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_prog_cxx_g=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_cxx_werror_flag=$ac_save_cxx_werror_flag -fi -{ echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6; } -if test "$ac_test_CXXFLAGS" = set; then - CXXFLAGS=$ac_save_CXXFLAGS -elif test $ac_cv_prog_cxx_g = yes; then - if test "$GXX" = yes; then - CXXFLAGS="-g -O2" - else - CXXFLAGS="-g" - fi -else - if test "$GXX" = yes; then - CXXFLAGS="-O2" - else - CXXFLAGS= - fi -fi -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -DEPDIR="${am__leading_dot}deps" - -ac_config_commands="$ac_config_commands depfiles" - - -am_make=${MAKE-make} -cat > confinc << 'END' -am__doit: - @echo done -.PHONY: am__doit -END -# If we don't find an include directive, just comment out the code. -{ echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 -echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6; } -am__include="#" -am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# We grep out `Entering directory' and `Leaving directory' -# messages which can occur if `w' ends up in MAKEFLAGS. -# In particular we don't look at `^make:' because GNU make might -# be invoked under some other name (usually "gmake"), in which -# case it prints its new name instead of `make'. -if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then - am__include=include - am__quote= - _am_result=GNU -fi -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then - am__include=.include - am__quote="\"" - _am_result=BSD - fi -fi - - -{ echo "$as_me:$LINENO: result: $_am_result" >&5 -echo "${ECHO_T}$_am_result" >&6; } -rm -f confinc confmf - -# Check whether --enable-dependency-tracking was given. -if test "${enable_dependency_tracking+set}" = set; then - enableval=$enable_dependency_tracking; -fi - -if test "x$enable_dependency_tracking" != xno; then - am_depcomp="$ac_aux_dir/depcomp" - AMDEPBACKSLASH='\' -fi - - -if test "x$enable_dependency_tracking" != xno; then - AMDEP_TRUE= - AMDEP_FALSE='#' -else - AMDEP_TRUE='#' - AMDEP_FALSE= -fi - - - - -depcc="$CXX" am_compiler_list= - -{ echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 -echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6; } -if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CXX_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - case $depmode in - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - none) break ;; - esac - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. - if depmode=$depmode \ - source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CXX_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CXX_dependencies_compiler_type=none -fi - -fi -{ echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 -echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6; } -CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type - - - -if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then - am__fastdepCXX_TRUE= - am__fastdepCXX_FALSE='#' -else - am__fastdepCXX_TRUE='#' - am__fastdepCXX_FALSE= -fi - - - -if test x"$enable_sse" != "xno"; then - if test "$GXX" = yes; then - if test "$ac_test_CXXFLAGS" != set; then - CXXFLAGS="-g -Wall -O2 -msse" - { echo "$as_me:$LINENO: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 -echo $ECHO_N "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works... $ECHO_C" >&6; } - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -int test; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - MSSE="-msse" - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - MSSE="" - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi - fi -else - MSSE="" -fi - -if test "$GXX" = yes; then - if test "$ac_test_CXXFLAGS" != set; then - CXXFLAGS="-g -Wall -O2 $MSSE -fno-exceptions" - { echo "$as_me:$LINENO: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 -echo $ECHO_N "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works... $ECHO_C" >&6; } - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -int test; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - NO_EXCEPTIONS="-fno-exceptions" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - NO_EXCEPTIONS="" - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi -fi - -if test "$GXX" = yes; then - if test "$ac_test_CXXFLAGS" != set; then - CXXFLAGS="-g -Wall -O2 $MSSE -fno-exceptions $NO_EXCEPTIONS -fno-pic" - { echo "$as_me:$LINENO: checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works" >&5 -echo $ECHO_N "checking whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works... $ECHO_C" >&6; } - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ -int test; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - NO_PIC="-fno-pic" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - NO_PIC="" - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi -fi - -CXXFLAGS="-g -Wall -O2 $MSSE $NO_EXCEPTIONS $NO_PIC" -if test x"$MSSE" = "x-msse"; then - { echo "$as_me:$LINENO: checking if the xmmintrin.h include can be used" >&5 -echo $ECHO_N "checking if the xmmintrin.h include can be used... $ECHO_C" >&6; } - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -int -main () -{ -int test; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - MSSE="" - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CXXFLAGS="-g -Wall -O2 $NO_EXCEPTIONS $NO_PIC" -fi - -# Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_AR+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$AR"; then - ac_cv_prog_AR="$AR" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AR="ar" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - - test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar" -fi -fi -AR=$ac_cv_prog_AR -if test -n "$AR"; then - { echo "$as_me:$LINENO: result: $AR" >&5 -echo "${ECHO_T}$AR" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. -set dummy ${ac_tool_prefix}ranlib; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$RANLIB"; then - ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -RANLIB=$ac_cv_prog_RANLIB -if test -n "$RANLIB"; then - { echo "$as_me:$LINENO: result: $RANLIB" >&5 -echo "${ECHO_T}$RANLIB" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_RANLIB"; then - ac_ct_RANLIB=$RANLIB - # Extract the first word of "ranlib", so it can be a program name with args. -set dummy ranlib; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_RANLIB"; then - ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_RANLIB="ranlib" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - -fi -fi -ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB -if test -n "$ac_ct_RANLIB"; then - { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 -echo "${ECHO_T}$ac_ct_RANLIB" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} -ac_tool_warned=yes ;; -esac - RANLIB=$ac_ct_RANLIB - fi -else - RANLIB="$ac_cv_prog_RANLIB" -fi - -# Extract the first word of "perl", so it can be a program name with args. -set dummy perl; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_path_PERL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $PERL in - [\\/]* | ?:[\\/]*) - ac_cv_path_PERL="$PERL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - - ;; -esac -fi -PERL=$ac_cv_path_PERL -if test -n "$PERL"; then - { echo "$as_me:$LINENO: result: $PERL" >&5 -echo "${ECHO_T}$PERL" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - - - - - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 -echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } -if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 -echo "${ECHO_T}$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null && { - test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || - test ! -s conftest.err - }; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - -{ echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 -echo $ECHO_N "checking for grep that handles long lines and -e... $ECHO_C" >&6; } -if test "${ac_cv_path_GREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Extract the first word of "grep ggrep" to use in msg output -if test -z "$GREP"; then -set dummy grep ggrep; ac_prog_name=$2 -if test "${ac_cv_path_GREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_path_GREP_found=false -# Loop through the user's path and test for each of PROGNAME-LIST -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in grep ggrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue - # Check for GNU ac_path_GREP and select it if it is found. - # Check for GNU $ac_path_GREP -case `"$ac_path_GREP" --version 2>&1` in -*GNU*) - ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; -*) - ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - echo 'GREP' >> "conftest.nl" - "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` - if test $ac_count -gt ${ac_path_GREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_GREP="$ac_path_GREP" - ac_path_GREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - - $ac_path_GREP_found && break 3 - done -done - -done -IFS=$as_save_IFS - - -fi - -GREP="$ac_cv_path_GREP" -if test -z "$GREP"; then - { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } -fi - -else - ac_cv_path_GREP=$GREP -fi - - -fi -{ echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 -echo "${ECHO_T}$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 - then ac_cv_path_EGREP="$GREP -E" - else - # Extract the first word of "egrep" to use in msg output -if test -z "$EGREP"; then -set dummy egrep; ac_prog_name=$2 -if test "${ac_cv_path_EGREP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_path_EGREP_found=false -# Loop through the user's path and test for each of PROGNAME-LIST -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_prog in egrep; do - for ac_exec_ext in '' $ac_executable_extensions; do - ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue - # Check for GNU ac_path_EGREP and select it if it is found. - # Check for GNU $ac_path_EGREP -case `"$ac_path_EGREP" --version 2>&1` in -*GNU*) - ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; -*) - ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - echo 'EGREP' >> "conftest.nl" - "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break - diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break - ac_count=`expr $ac_count + 1` - if test $ac_count -gt ${ac_path_EGREP_max-0}; then - # Best one so far, save it but keep looking for a better one - ac_cv_path_EGREP="$ac_path_EGREP" - ac_path_EGREP_max=$ac_count - fi - # 10*(2^10) chars as input seems more than enough - test $ac_count -gt 10 && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out;; -esac - - - $ac_path_EGREP_found && break 3 - done -done - -done -IFS=$as_save_IFS - - -fi - -EGREP="$ac_cv_path_EGREP" -if test -z "$EGREP"; then - { { echo "$as_me:$LINENO: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 -echo "$as_me: error: no acceptable $ac_prog_name could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} - { (exit 1); exit 1; }; } -fi - -else - ac_cv_path_EGREP=$EGREP -fi - - - fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 -echo "${ECHO_T}$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6; } -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_header_stdc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_header_stdc=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then - : -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -ac_cv_header_stdc=no -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi - - -fi -fi -{ echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_Header=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - -{ echo "$as_me:$LINENO: checking for int" >&5 -echo $ECHO_N "checking for int... $ECHO_C" >&6; } -if test "${ac_cv_type_int+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -typedef int ac__type_new_; -int -main () -{ -if ((ac__type_new_ *) 0) - return 0; -if (sizeof (ac__type_new_)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_type_int=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_type_int=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_type_int" >&5 -echo "${ECHO_T}$ac_cv_type_int" >&6; } - -# The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ echo "$as_me:$LINENO: checking size of int" >&5 -echo $ECHO_N "checking size of int... $ECHO_C" >&6; } -if test "${ac_cv_sizeof_int+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test "$cross_compiling" = yes; then - # Depending upon the size, compute the lo and hi bounds. -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - typedef int ac__type_sizeof_; -int -main () -{ -static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_lo=0 ac_mid=0 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - typedef int ac__type_sizeof_; -int -main () -{ -static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_hi=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_lo=`expr $ac_mid + 1` - if test $ac_lo -le $ac_mid; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid + 1` -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - typedef int ac__type_sizeof_; -int -main () -{ -static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) < 0)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_hi=-1 ac_mid=-1 - while :; do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - typedef int ac__type_sizeof_; -int -main () -{ -static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) >= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_lo=$ac_mid; break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_hi=`expr '(' $ac_mid ')' - 1` - if test $ac_mid -le $ac_hi; then - ac_lo= ac_hi= - break - fi - ac_mid=`expr 2 '*' $ac_mid` -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - done -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_lo= ac_hi= -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -# Binary search between lo and hi bounds. -while test "x$ac_lo" != "x$ac_hi"; do - ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - typedef int ac__type_sizeof_; -int -main () -{ -static int test_array [1 - 2 * !(((long int) (sizeof (ac__type_sizeof_))) <= $ac_mid)]; -test_array [0] = 0 - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_hi=$ac_mid -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_lo=`expr '(' $ac_mid ')' + 1` -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -done -case $ac_lo in -?*) ac_cv_sizeof_int=$ac_lo;; -'') if test "$ac_cv_type_int" = yes; then - { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (int) -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } - else - ac_cv_sizeof_int=0 - fi ;; -esac -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - typedef int ac__type_sizeof_; -static long int longval () { return (long int) (sizeof (ac__type_sizeof_)); } -static unsigned long int ulongval () { return (long int) (sizeof (ac__type_sizeof_)); } -#include -#include -int -main () -{ - - FILE *f = fopen ("conftest.val", "w"); - if (! f) - return 1; - if (((long int) (sizeof (ac__type_sizeof_))) < 0) - { - long int i = longval (); - if (i != ((long int) (sizeof (ac__type_sizeof_)))) - return 1; - fprintf (f, "%ld\n", i); - } - else - { - unsigned long int i = ulongval (); - if (i != ((long int) (sizeof (ac__type_sizeof_)))) - return 1; - fprintf (f, "%lu\n", i); - } - return ferror (f) || fclose (f) != 0; - - ; - return 0; -} -_ACEOF -rm -f conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_sizeof_int=`cat conftest.val` -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -( exit $ac_status ) -if test "$ac_cv_type_int" = yes; then - { { echo "$as_me:$LINENO: error: cannot compute sizeof (int) -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute sizeof (int) -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } - else - ac_cv_sizeof_int=0 - fi -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -rm -f conftest.val -fi -{ echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5 -echo "${ECHO_T}$ac_cv_sizeof_int" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_INT $ac_cv_sizeof_int -_ACEOF - - - -if test $ac_cv_sizeof_int -lt 4; then - { { echo "$as_me:$LINENO: error: only 32 bit or better CPUs are supported" >&5 -echo "$as_me: error: only 32 bit or better CPUs are supported" >&2;} - { (exit 1); exit 1; }; } -fi - -{ echo "$as_me:$LINENO: checking for working bool" >&5 -echo $ECHO_N "checking for working bool... $ECHO_C" >&6; } -if test "${ac_cv_cxx_bool+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -int -main () -{ - -bool flag; - - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - ac_cv_cxx_bool=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_cv_cxx_bool=no -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ echo "$as_me:$LINENO: result: $ac_cv_cxx_bool" >&5 -echo "${ECHO_T}$ac_cv_cxx_bool" >&6; } - -if test $ac_cv_cxx_bool = no; then - RESID_HAVE_BOOL=0 -else - RESID_HAVE_BOOL=1 -fi - -if test x"$MSSE" = "x-msse"; then - RESID_USE_SSE=1 - - -if true; then - USE_SSE_TRUE= - USE_SSE_FALSE='#' -else - USE_SSE_TRUE='#' - USE_SSE_FALSE= -fi - -else - RESID_USE_SSE=0 - - -if false; then - USE_SSE_TRUE= - USE_SSE_FALSE='#' -else - USE_SSE_TRUE='#' - USE_SSE_FALSE= -fi - -fi - - - - - - - -for ac_func in logf expf -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && - $as_test_x conftest$ac_exeext; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval echo '${'$as_ac_var'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } -if test `eval echo '${'$as_ac_var'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - -{ echo "$as_me:$LINENO: checking if the logf prototype is present" >&5 -echo $ECHO_N "checking if the logf prototype is present... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - #include -int -main () -{ -printf("%d",logf); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - HAVE_LOGF_PROTOTYPE=1 - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - HAVE_LOGF_PROTOTYPE=0 - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -{ echo "$as_me:$LINENO: checking if the expf prototype is present" >&5 -echo $ECHO_N "checking if the expf prototype is present... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - #include -int -main () -{ -printf("%d",expf); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (ac_try="$ac_compile" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_compile") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_cxx_werror_flag" || - test ! -s conftest.err - } && test -s conftest.$ac_objext; then - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - HAVE_EXPF_PROTOTYPE=1 - -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } - HAVE_EXPF_PROTOTYPE=0 - -fi - -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - - - - -ac_config_files="$ac_config_files Makefile siddefs-fp.h" - -cat >confcache <<\_ACEOF -# This file is a shell script that caches the results of configure -# tests run on this system so they can be shared between configure -# scripts and configure runs, see configure's option --config-cache. -# It is not useful on other systems. If it contains results you don't -# want to keep, you may remove or edit it. -# -# config.status only pays attention to the cache file if you give it -# the --recheck option to rerun configure. -# -# `ac_cv_env_foo' variables (set or unset) will be overridden when -# loading this file, other *unset* `ac_cv_foo' will be assigned the -# following values. - -_ACEOF - -# The following way of writing the cache mishandles newlines in values, -# but we know of no workaround that is simple, portable, and efficient. -# So, we kill variables containing newlines. -# Ultrix sh set writes to stderr and can't be redirected directly, -# and sets the high bit in the cache file unless we assign to the vars. -( - for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do - eval ac_val=\$$ac_var - case $ac_val in #( - *${as_nl}*) - case $ac_var in #( - *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; - esac - case $ac_var in #( - _ | IFS | as_nl) ;; #( - *) $as_unset $ac_var ;; - esac ;; - esac - done - - (set) 2>&1 | - case $as_nl`(ac_space=' '; set) 2>&1` in #( - *${as_nl}ac_space=\ *) - # `set' does not quote correctly, so add quotes (double-quote - # substitution turns \\\\ into \\, and sed turns \\ into \). - sed -n \ - "s/'/'\\\\''/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" - ;; #( - *) - # `set' quotes correctly as required by POSIX, so do not add quotes. - sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" - ;; - esac | - sort -) | - sed ' - /^ac_cv_env_/b end - t clear - :clear - s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ - t end - s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ - :end' >>confcache -if diff "$cache_file" confcache >/dev/null 2>&1; then :; else - if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && - { echo "$as_me:$LINENO: updating cache $cache_file" >&5 -echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file - else - { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 -echo "$as_me: not updating unwritable cache $cache_file" >&6;} - fi -fi -rm -f confcache - -test "x$prefix" = xNONE && prefix=$ac_default_prefix -# Let make expand exec_prefix. -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - -# Transform confdefs.h into DEFS. -# Protect against shell expansion while executing Makefile rules. -# Protect against Makefile macro expansion. -# -# If the first sed substitution is executed (which looks for macros that -# take arguments), then branch to the quote section. Otherwise, -# look for a macro that doesn't take arguments. -ac_script=' -t clear -:clear -s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g -t quote -s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g -t quote -b any -:quote -s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g -s/\[/\\&/g -s/\]/\\&/g -s/\$/$$/g -H -:any -${ - g - s/^\n// - s/\n/ /g - p -} -' -DEFS=`sed -n "$ac_script" confdefs.h` - - -ac_libobjs= -ac_ltlibobjs= -for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue - # 1. Remove the extension, and $U if already installed. - ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' - ac_i=`echo "$ac_i" | sed "$ac_script"` - # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR - # will be set to the directory where LIBOBJS objects are built. - ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' -done -LIBOBJS=$ac_libobjs - -LTLIBOBJS=$ac_ltlibobjs - - -if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"AMDEP\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${USE_SSE_TRUE}" && test -z "${USE_SSE_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"USE_SSE\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"USE_SSE\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi -if test -z "${USE_SSE_TRUE}" && test -z "${USE_SSE_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"USE_SSE\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"USE_SSE\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi - -: ${CONFIG_STATUS=./config.status} -ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in - *posix*) set -o posix ;; -esac - -fi - - - - -# PATH needs CR -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset -else - as_unset=false -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -as_nl=' -' -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - { (exit 1); exit 1; } -fi - -# Work around bugs in pre-3.0 UWIN ksh. -for as_var in ENV MAIL MAILPATH -do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var - fi -done - -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - - -# Name of the executable. -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# CDPATH. -$as_unset CDPATH - - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line after each line using $LINENO; the second 'sed' - # does the real work. The second script uses 'N' to pair each - # line-number line with the line containing $LINENO, and appends - # trailing '-' during substitution so that $LINENO is not a special - # case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # scripts with optimization help from Paolo Bonzini. Blame Lee - # E. McMahon (1931-1989) for sed's syntax. :-) - sed -n ' - p - /[$]LINENO/= - ' <$as_myself | - sed ' - s/[$]LINENO.*/&-/ - t lineno - b - :lineno - N - :loop - s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ - t loop - s/-\n.*// - ' >$as_me.lineno && - chmod +x "$as_me.lineno" || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensitive to this). - . "./$as_me.lineno" - # Exit status is that of the last command. - exit -} - - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in --n*) - case `echo 'x\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - *) ECHO_C='\c';; - esac;; -*) - ECHO_N='-n';; -esac - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir -fi -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln -else - as_ln_s='cp -p' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - -if mkdir -p . 2>/dev/null; then - as_mkdir_p=: -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 - -# Save the log message, to keep $[0] and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.61. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -_ACEOF - -cat >>$CONFIG_STATUS <<_ACEOF -# Files that config.status was made for. -config_files="$ac_config_files" -config_commands="$ac_config_commands" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. - -Usage: $0 [OPTIONS] [FILE]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Configuration commands: -$config_commands - -Report bugs to ." - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -ac_cs_version="\\ -config.status -configured by $0, generated by GNU Autoconf 2.61, - with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" - -Copyright (C) 2006 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='$ac_pwd' -srcdir='$srcdir' -INSTALL='$INSTALL' -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - echo "$ac_cs_version"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) { echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } ;; - - *) ac_config_targets="$ac_config_targets $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -if \$ac_cs_recheck; then - echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - CONFIG_SHELL=$SHELL - export CONFIG_SHELL - exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -fi - -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - echo "$ac_log" -} >&5 - -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF -# -# INIT-COMMANDS -# -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" - -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "siddefs-fp.h") CONFIG_FILES="$CONFIG_FILES siddefs-fp.h" ;; - - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files - test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= - trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status -' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || -{ - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } -} - -# -# Set up the sed scripts for CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "$CONFIG_FILES"; then - -_ACEOF - - - -ac_delim='%!_!# ' -for ac_last_try in false false false false false :; do - cat >conf$$subs.sed <<_ACEOF -SHELL!$SHELL$ac_delim -PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim -PACKAGE_NAME!$PACKAGE_NAME$ac_delim -PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim -PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim -PACKAGE_STRING!$PACKAGE_STRING$ac_delim -PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim -exec_prefix!$exec_prefix$ac_delim -prefix!$prefix$ac_delim -program_transform_name!$program_transform_name$ac_delim -bindir!$bindir$ac_delim -sbindir!$sbindir$ac_delim -libexecdir!$libexecdir$ac_delim -datarootdir!$datarootdir$ac_delim -datadir!$datadir$ac_delim -sysconfdir!$sysconfdir$ac_delim -sharedstatedir!$sharedstatedir$ac_delim -localstatedir!$localstatedir$ac_delim -includedir!$includedir$ac_delim -oldincludedir!$oldincludedir$ac_delim -docdir!$docdir$ac_delim -infodir!$infodir$ac_delim -htmldir!$htmldir$ac_delim -dvidir!$dvidir$ac_delim -pdfdir!$pdfdir$ac_delim -psdir!$psdir$ac_delim -libdir!$libdir$ac_delim -localedir!$localedir$ac_delim -mandir!$mandir$ac_delim -DEFS!$DEFS$ac_delim -ECHO_C!$ECHO_C$ac_delim -ECHO_N!$ECHO_N$ac_delim -ECHO_T!$ECHO_T$ac_delim -LIBS!$LIBS$ac_delim -build_alias!$build_alias$ac_delim -host_alias!$host_alias$ac_delim -target_alias!$target_alias$ac_delim -INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim -INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim -INSTALL_DATA!$INSTALL_DATA$ac_delim -CYGPATH_W!$CYGPATH_W$ac_delim -PACKAGE!$PACKAGE$ac_delim -VERSION!$VERSION$ac_delim -ACLOCAL!$ACLOCAL$ac_delim -AUTOCONF!$AUTOCONF$ac_delim -AUTOMAKE!$AUTOMAKE$ac_delim -AUTOHEADER!$AUTOHEADER$ac_delim -MAKEINFO!$MAKEINFO$ac_delim -install_sh!$install_sh$ac_delim -STRIP!$STRIP$ac_delim -INSTALL_STRIP_PROGRAM!$INSTALL_STRIP_PROGRAM$ac_delim -mkdir_p!$mkdir_p$ac_delim -AWK!$AWK$ac_delim -SET_MAKE!$SET_MAKE$ac_delim -am__leading_dot!$am__leading_dot$ac_delim -AMTAR!$AMTAR$ac_delim -am__tar!$am__tar$ac_delim -am__untar!$am__untar$ac_delim -RESID_INLINE!$RESID_INLINE$ac_delim -CXX!$CXX$ac_delim -CXXFLAGS!$CXXFLAGS$ac_delim -LDFLAGS!$LDFLAGS$ac_delim -CPPFLAGS!$CPPFLAGS$ac_delim -ac_ct_CXX!$ac_ct_CXX$ac_delim -EXEEXT!$EXEEXT$ac_delim -OBJEXT!$OBJEXT$ac_delim -DEPDIR!$DEPDIR$ac_delim -am__include!$am__include$ac_delim -am__quote!$am__quote$ac_delim -AMDEP_TRUE!$AMDEP_TRUE$ac_delim -AMDEP_FALSE!$AMDEP_FALSE$ac_delim -AMDEPBACKSLASH!$AMDEPBACKSLASH$ac_delim -CXXDEPMODE!$CXXDEPMODE$ac_delim -am__fastdepCXX_TRUE!$am__fastdepCXX_TRUE$ac_delim -am__fastdepCXX_FALSE!$am__fastdepCXX_FALSE$ac_delim -AR!$AR$ac_delim -RANLIB!$RANLIB$ac_delim -PERL!$PERL$ac_delim -CXXCPP!$CXXCPP$ac_delim -GREP!$GREP$ac_delim -EGREP!$EGREP$ac_delim -USE_SSE_TRUE!$USE_SSE_TRUE$ac_delim -USE_SSE_FALSE!$USE_SSE_FALSE$ac_delim -RESID_HAVE_BOOL!$RESID_HAVE_BOOL$ac_delim -RESID_USE_SSE!$RESID_USE_SSE$ac_delim -HAVE_LOGF_PROTOTYPE!$HAVE_LOGF_PROTOTYPE$ac_delim -HAVE_EXPF_PROTOTYPE!$HAVE_EXPF_PROTOTYPE$ac_delim -LIBOBJS!$LIBOBJS$ac_delim -LTLIBOBJS!$LTLIBOBJS$ac_delim -_ACEOF - - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 89; then - break - elif $ac_last_try; then - { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} - { (exit 1); exit 1; }; } - else - ac_delim="$ac_delim!$ac_delim _$ac_delim!! " - fi -done - -ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed` -if test -n "$ac_eof"; then - ac_eof=`echo "$ac_eof" | sort -nru | sed 1q` - ac_eof=`expr $ac_eof + 1` -fi - -cat >>$CONFIG_STATUS <<_ACEOF -cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end -_ACEOF -sed ' -s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g -s/^/s,@/; s/!/@,|#_!!_#|/ -:n -t n -s/'"$ac_delim"'$/,g/; t -s/$/\\/; p -N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n -' >>$CONFIG_STATUS >$CONFIG_STATUS <<_ACEOF -:end -s/|#_!!_#|//g -CEOF$ac_eof -_ACEOF - - -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ -s/:*$// -s/^[^=]*=[ ]*$// -}' -fi - -cat >>$CONFIG_STATUS <<\_ACEOF -fi # test -n "$CONFIG_FILES" - - -for ac_tag in :F $CONFIG_FILES :C $CONFIG_COMMANDS -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 -echo "$as_me: error: Invalid tag $ac_tag." >&2;} - { (exit 1); exit 1; }; };; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 -echo "$as_me: error: cannot find input file: $ac_f" >&2;} - { (exit 1); exit 1; }; };; - esac - ac_file_inputs="$ac_file_inputs $ac_f" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input="Generated from "`IFS=: - echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure." - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - fi - - case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin";; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { as_dir="$ac_dir" - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 -echo "$as_me: error: cannot create directory $as_dir" >&2;} - { (exit 1); exit 1; }; }; } - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac -_ACEOF - -cat >>$CONFIG_STATUS <<\_ACEOF -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= - -case `sed -n '/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p -' $ac_file_inputs` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} -_ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - ac_datarootdir_hack=' - s&@datadir@&$datadir&g - s&@docdir@&$docdir&g - s&@infodir@&$infodir&g - s&@localedir@&$localedir&g - s&@mandir@&$mandir&g - s&\\\${datarootdir}&$datarootdir&g' ;; -esac -_ACEOF - -# Neutralize VPATH when `$srcdir' = `.'. -# Shell code in configure.ac might set extrasub. -# FIXME: do we really want to maintain this feature? -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub -$extrasub -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s&@configure_input@&$configure_input&;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -$ac_datarootdir_hack -" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && - { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 -echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} - - rm -f "$tmp/stdin" - case $ac_file in - -) cat "$tmp/out"; rm -f "$tmp/out";; - *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;; - esac - ;; - - - :C) { echo "$as_me:$LINENO: executing $ac_file commands" >&5 -echo "$as_me: executing $ac_file commands" >&6;} - ;; - esac - - - case $ac_file$ac_mode in - "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do - # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # So let's grep whole file. - if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -echo X"$mf" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - { as_dir=$dirpart/$fdir - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 -echo "$as_me: error: cannot create directory $as_dir" >&2;} - { (exit 1); exit 1; }; }; } - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done -done - ;; - - esac -done # for ac_tag - - -{ (exit 0); exit 0; } -_ACEOF -chmod +x $CONFIG_STATUS -ac_clean_files=$ac_clean_files_save - - -# configure is writing to config.log, and then calls config.status. -# config.status does its own redirection, appending to config.log. -# Unfortunately, on DOS this fails, as config.log is still kept open -# by configure, so config.status won't be able to write to it; its -# output is simply discarded. So we exec the FD to /dev/null, -# effectively closing config.log, so it can be properly (re)opened and -# appended to by config.status. When coming back to configure, we -# need to make the FD available again. -if test "$no_create" != yes; then - ac_cs_success=: - ac_config_status_args= - test "$silent" = yes && - ac_config_status_args="$ac_config_status_args --quiet" - exec 5>/dev/null - $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false - exec 5>>config.log - # Use ||, not &&, to avoid exiting from the if with $? = 1, which - # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } -fi - diff --git a/src/sound/resid-fp/configure.in b/src/sound/resid-fp/configure.in deleted file mode 100644 index f4b3b5731c..0000000000 --- a/src/sound/resid-fp/configure.in +++ /dev/null @@ -1,166 +0,0 @@ -dnl Process this file with autoconf to produce a configure script. -AC_INIT(sid.h) - -dnl Use Automake -AM_INIT_AUTOMAKE(resid, 0.16vice) -LTVERSION=5:0:0 - -dnl Use C++ for tests. -AC_LANG_CPLUSPLUS - -dnl Enable inlining. -AC_ARG_ENABLE(inline, -[ --enable-inline enable inlining of functions [default=yes]]) -AC_ARG_ENABLE(sse, -[ --enable-sse enable the use of SSE [default=yes]]) - -if test "$enable_inline" != no; then - RESID_INLINE=inline -else - RESID_INLINE= -fi - -AC_SUBST(RESID_INLINE) - -dnl Checks for programs. -AC_PROG_CXX - -dnl Set CXXFLAGS for g++. Use -msse if supported. -if test x"$enable_sse" != "xno"; then - if test "$GXX" = yes; then - if test "$ac_test_CXXFLAGS" != set; then - CXXFLAGS="-g -Wall -O2 -msse" - AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works]) - AC_TRY_COMPILE([], - [int test;], - [ AC_MSG_RESULT(yes) - MSSE="-msse" - ], - [ AC_MSG_RESULT(no) - MSSE="" - ]) - fi - fi -else - MSSE="" -fi - -dnl Set CXXFLAGS for g++. Use -fno-exceptions if supported. -if test "$GXX" = yes; then - if test "$ac_test_CXXFLAGS" != set; then - CXXFLAGS="-g -Wall -O2 $MSSE -fno-exceptions" - AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works]) - AC_TRY_COMPILE([], - [int test;], - [ AC_MSG_RESULT(yes) - NO_EXCEPTIONS="-fno-exceptions" ], - [ AC_MSG_RESULT(no) - NO_EXCEPTIONS="" - ]) - fi -fi - -dnl Set CXXFLAGS for g++. Use -fno-pic if supported. -if test "$GXX" = yes; then - if test "$ac_test_CXXFLAGS" != set; then - CXXFLAGS="-g -Wall -O2 $MSSE -fno-exceptions $NO_EXCEPTIONS -fno-pic" - AC_MSG_CHECKING([whether the C++ compiler ($CXX $CXXFLAGS $LDFLAGS) works]) - AC_TRY_COMPILE([], - [int test;], - [ AC_MSG_RESULT(yes) - NO_PIC="-fno-pic" ], - [ AC_MSG_RESULT(no) - NO_PIC="" - ]) - fi -fi - -CXXFLAGS="-g -Wall -O2 $MSSE $NO_EXCEPTIONS $NO_PIC" -if test x"$MSSE" = "x-msse"; then - AC_MSG_CHECKING([if the xmmintrin.h include can be used]) - AC_TRY_COMPILE([#include ], - [int test;], - [ AC_MSG_RESULT(yes) - ], - [ AC_MSG_RESULT(no) - MSSE="" - ]) - CXXFLAGS="-g -Wall -O2 $NO_EXCEPTIONS $NO_PIC" -fi - -AC_CHECK_PROG(AR, ar, ar, ar) -AC_PROG_RANLIB -AC_PATH_PROG(PERL, perl) - -dnl Libtool - -dnl AC_DISABLE_SHARED -dnl AM_PROG_LIBTOOL -dnl AC_SUBST(LIBTOOL_DEPS) -dnl AC_SUBST(LTVERSION) - -dnl Checks for libraries. - -dnl Checks for header files. - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_CHECK_SIZEOF(int, 4) - -if test $ac_cv_sizeof_int -lt 4; then - AC_MSG_ERROR([only 32 bit or better CPUs are supported]) -fi - -AC_CACHE_CHECK([for working bool], ac_cv_cxx_bool, -[AC_TRY_COMPILE(, -[ -bool flag; -], -ac_cv_cxx_bool=yes, ac_cv_cxx_bool=no)]) - -if test $ac_cv_cxx_bool = no; then - RESID_HAVE_BOOL=0 -else - RESID_HAVE_BOOL=1 -fi - -if test x"$MSSE" = "x-msse"; then - RESID_USE_SSE=1 - AM_CONDITIONAL(USE_SSE, true) -else - RESID_USE_SSE=0 - AM_CONDITIONAL(USE_SSE, false) -fi - -AC_SUBST(RESID_HAVE_BOOL) -AC_SUBST(RESID_USE_SSE) - -dnl Checks for library functions. - -AC_CHECK_FUNCS(logf expf) - -AC_MSG_CHECKING([if the logf prototype is present]) -AC_TRY_COMPILE([#include - #include ], - [printf("%d",logf);], - [ AC_MSG_RESULT(yes) - HAVE_LOGF_PROTOTYPE=1 - ], - [ AC_MSG_RESULT(no) - HAVE_LOGF_PROTOTYPE=0 - ]) - -AC_MSG_CHECKING([if the expf prototype is present]) -AC_TRY_COMPILE([#include - #include ], - [printf("%d",expf);], - [ AC_MSG_RESULT(yes) - HAVE_EXPF_PROTOTYPE=1 - ], - [ AC_MSG_RESULT(no) - HAVE_EXPF_PROTOTYPE=0 - ]) - -AC_SUBST(HAVE_LOGF_PROTOTYPE) -AC_SUBST(HAVE_EXPF_PROTOTYPE) - -AC_OUTPUT(Makefile siddefs-fp.h) diff --git a/src/sound/resid-fp/convolve-sse.cc b/src/sound/resid-fp/convolve-sse.cc deleted file mode 100644 index daf3979f25..0000000000 --- a/src/sound/resid-fp/convolve-sse.cc +++ /dev/null @@ -1,76 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- -#include -#include "sid.h" - -#if (RESID_USE_SSE==1) - -#include - -float convolve_sse(const float *a, const float *b, int n) -{ - float out = 0.f; - __m128 out4 = { 0, 0, 0, 0 }; - - /* examine if we can use aligned loads on both pointers */ - int diff = (int) (a - b) & 0xf; - /* long cast is no-op for x86-32, but x86-64 gcc needs 64 bit intermediate - * to convince compiler we mean this. */ - unsigned int a_align = (unsigned int) (uintptr_t) a & 0xf; - - /* advance if necessary. We can't let n fall < 0, so no while (n --). */ - while (n > 0 && a_align != 0 && a_align != 16) { - out += (*(a ++)) * (*(b ++)); - --n; - a_align += 4; - } - - int n4 = n / 4; - if (diff == 0) { - for (int i = 0; i < n4; i ++) { - out4 = _mm_add_ps(out4, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b))); - a += 4; - b += 4; - } - } else { - /* XXX loadu is 4x slower than load, at least. We could at 4x memory - * use prepare versions of b aligned for any a alignment. We could - * also issue aligned loads and shuffle the halves at each iteration. - * Initial results indicate only very small improvements. */ - for (int i = 0; i < n4; i ++) { - out4 = _mm_add_ps(out4, _mm_mul_ps(_mm_load_ps(a), _mm_loadu_ps(b))); - a += 4; - b += 4; - } - } - - out4 = _mm_add_ps(_mm_movehl_ps(out4, out4), out4); - out4 = _mm_add_ss(_mm_shuffle_ps(out4, out4, 1), out4); - float out_tmp; - _mm_store_ss(&out_tmp, out4); - out += out_tmp; - - n &= 3; - - while (n --) - out += (*(a ++)) * (*(b ++)); - - return out; -} -#endif diff --git a/src/sound/resid-fp/convolve.cc b/src/sound/resid-fp/convolve.cc deleted file mode 100644 index b028ace86f..0000000000 --- a/src/sound/resid-fp/convolve.cc +++ /dev/null @@ -1,27 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -float convolve(const float *a, const float *b, int n) -{ - float out = 0.f; - while (n --) - out += (*(a ++)) * (*(b ++)); - return out; -} - diff --git a/src/sound/resid-fp/envelope.cc b/src/sound/resid-fp/envelope.cc deleted file mode 100644 index 5417adc430..0000000000 --- a/src/sound/resid-fp/envelope.cc +++ /dev/null @@ -1,254 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#define __ENVELOPE_CC__ -#include "envelope.h" - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -EnvelopeGeneratorFP::EnvelopeGeneratorFP() -{ - reset(); -} - -// ---------------------------------------------------------------------------- -// SID reset. -// ---------------------------------------------------------------------------- -void EnvelopeGeneratorFP::reset() -{ - envelope_counter = 0; - - attack = 0; - decay = 0; - sustain = 0; - release = 0; - - gate = 0; - - rate_counter = 0; - exponential_counter = 0; - exponential_counter_period = 1; - - state = RELEASE; - rate_period = rate_counter_period[release]; - hold_zero = true; -} - - -// Rate counter periods are calculated from the Envelope Rates table in -// the Programmer's Reference Guide. The rate counter period is the number of -// cycles between each increment of the envelope counter. -// The rates have been verified by sampling ENV3. -// -// The rate counter is a 16 bit register which is incremented each cycle. -// When the counter reaches a specific comparison value, the envelope counter -// is incremented (attack) or decremented (decay/release) and the -// counter is zeroed. -// -// NB! Sampling ENV3 shows that the calculated values are not exact. -// It may seem like most calculated values have been rounded (.5 is rounded -// down) and 1 has beed added to the result. A possible explanation for this -// is that the SID designers have used the calculated values directly -// as rate counter comparison values, not considering a one cycle delay to -// zero the counter. This would yield an actual period of comparison value + 1. -// -// The time of the first envelope count can not be exactly controlled, except -// possibly by resetting the chip. Because of this we cannot do cycle exact -// sampling and must devise another method to calculate the rate counter -// periods. -// -// The exact rate counter periods can be determined e.g. by counting the number -// of cycles from envelope level 1 to envelope level 129, and dividing the -// number of cycles by 128. CIA1 timer A and B in linked mode can perform -// the cycle count. This is the method used to find the rates below. -// -// To avoid the ADSR delay bug, sampling of ENV3 should be done using -// sustain = release = 0. This ensures that the attack state will not lower -// the current rate counter period. -// -// The ENV3 sampling code below yields a maximum timing error of 14 cycles. -// lda #$01 -// l1: cmp $d41c -// bne l1 -// ... -// lda #$ff -// l2: cmp $d41c -// bne l2 -// -// This yields a maximum error for the calculated rate period of 14/128 cycles. -// The described method is thus sufficient for exact calculation of the rate -// periods. -// -reg16 EnvelopeGeneratorFP::rate_counter_period[] = { - 9, // 2ms*1.0MHz/256 = 7.81 - 32, // 8ms*1.0MHz/256 = 31.25 - 63, // 16ms*1.0MHz/256 = 62.50 - 95, // 24ms*1.0MHz/256 = 93.75 - 149, // 38ms*1.0MHz/256 = 148.44 - 220, // 56ms*1.0MHz/256 = 218.75 - 267, // 68ms*1.0MHz/256 = 265.63 - 313, // 80ms*1.0MHz/256 = 312.50 - 392, // 100ms*1.0MHz/256 = 390.63 - 977, // 250ms*1.0MHz/256 = 976.56 - 1954, // 500ms*1.0MHz/256 = 1953.13 - 3126, // 800ms*1.0MHz/256 = 3125.00 - 3907, // 1 s*1.0MHz/256 = 3906.25 - 11720, // 3 s*1.0MHz/256 = 11718.75 - 19532, // 5 s*1.0MHz/256 = 19531.25 - 31251 // 8 s*1.0MHz/256 = 31250.00 -}; - - -// For decay and release, the clock to the envelope counter is sequentially -// divided by 1, 2, 4, 8, 16, 30, 1 to create a piece-wise linear approximation -// of an exponential. The exponential counter period is loaded at the envelope -// counter values 255, 93, 54, 26, 14, 6, 0. The period can be different for the -// same envelope counter value, depending on whether the envelope has been -// rising (attack -> release) or sinking (decay/release). -// -// Since it is not possible to reset the rate counter (the test bit has no -// influence on the envelope generator whatsoever) a method must be devised to -// do cycle exact sampling of ENV3 to do the investigation. This is possible -// with knowledge of the rate period for A=0, found above. -// -// The CPU can be synchronized with ENV3 by first synchronizing with the rate -// counter by setting A=0 and wait in a carefully timed loop for the envelope -// counter _not_ to change for 9 cycles. We can then wait for a specific value -// of ENV3 with another timed loop to fully synchronize with ENV3. -// -// At the first period when an exponential counter period larger than one -// is used (decay or relase), one extra cycle is spent before the envelope is -// decremented. The envelope output is then delayed one cycle until the state -// is changed to attack. Now one cycle less will be spent before the envelope -// is incremented, and the situation is normalized. -// The delay is probably caused by the comparison with the exponential counter, -// and does not seem to affect the rate counter. This has been verified by -// timing 256 consecutive complete envelopes with A = D = R = 1, S = 0, using -// CIA1 timer A and B in linked mode. If the rate counter is not affected the -// period of each complete envelope is -// (255 + 162*1 + 39*2 + 28*4 + 12*8 + 8*16 + 6*30)*32 = 756*32 = 32352 -// which corresponds exactly to the timed value divided by the number of -// complete envelopes. -// NB! This one cycle delay is not modeled. - - -// From the sustain levels it follows that both the low and high 4 bits of the -// envelope counter are compared to the 4-bit sustain value. -// This has been verified by sampling ENV3. -// -reg8 EnvelopeGeneratorFP::sustain_level[] = { - 0x00, - 0x11, - 0x22, - 0x33, - 0x44, - 0x55, - 0x66, - 0x77, - 0x88, - 0x99, - 0xaa, - 0xbb, - 0xcc, - 0xdd, - 0xee, - 0xff, -}; - - -// ---------------------------------------------------------------------------- -// Register functions. -// ---------------------------------------------------------------------------- -void EnvelopeGeneratorFP::writeCONTROL_REG(reg8 control) -{ - reg8 gate_next = control & 0x01; - - // The rate counter is never reset, thus there will be a delay before the - // envelope counter starts counting up (attack) or down (release). - - // Gate bit on: Start attack, decay, sustain. - if (!gate && gate_next) { - state = ATTACK; - update_rate_period(rate_counter_period[attack]); - - // Switching to attack state unlocks the zero freeze. - hold_zero = false; - } - // Gate bit off: Start release. - else if (gate && !gate_next) { - state = RELEASE; - update_rate_period(rate_counter_period[release]); - } - - gate = gate_next; -} - -void EnvelopeGeneratorFP::writeATTACK_DECAY(reg8 attack_decay) -{ - attack = (attack_decay >> 4) & 0x0f; - decay = attack_decay & 0x0f; - if (state == ATTACK) { - update_rate_period(rate_counter_period[attack]); - } - else if (state == DECAY_SUSTAIN) { - update_rate_period(rate_counter_period[decay]); - } -} - -void EnvelopeGeneratorFP::writeSUSTAIN_RELEASE(reg8 sustain_release) -{ - sustain = (sustain_release >> 4) & 0x0f; - release = sustain_release & 0x0f; - if (state == RELEASE) { - update_rate_period(rate_counter_period[release]); - } -} - -reg8 EnvelopeGeneratorFP::readENV() -{ - return output(); -} - -void EnvelopeGeneratorFP::update_rate_period(reg16 newperiod) -{ - rate_period = newperiod; - - /* The ADSR counter is XOR shift register with 0x7fff unique values. - * If the rate_period is adjusted to a value already seen in this cycle, - * the register will wrap around. This is known as the ADSR delay bug. - * - * To simplify the hot path calculation, we simulate this through observing - * that we add the 0x7fff cycle delay by changing the rate_counter variable - * directly. This takes care of the 99 % common case. However, playroutine - * could make multiple consequtive rate_period adjustments, in which case we - * need to cancel the previous adjustment. */ - - /* if the new period exeecds 0x7fff, we need to wrap */ - if (rate_period - rate_counter > 0x7fff) - rate_counter += 0x7fff; - - /* simulate 0x7fff wraparound, if the period-to-be-written - * is less than the current value. */ - if (rate_period <= rate_counter) - rate_counter -= 0x7fff; - - /* at this point it should be impossible for - * rate_counter >= rate_period. If it is, there is a bug... */ -} diff --git a/src/sound/resid-fp/envelope.h b/src/sound/resid-fp/envelope.h deleted file mode 100644 index af0764ccd6..0000000000 --- a/src/sound/resid-fp/envelope.h +++ /dev/null @@ -1,174 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#ifndef __ENVELOPE_H__ -#define __ENVELOPE_H__ - -#include "siddefs-fp.h" - -// ---------------------------------------------------------------------------- -// A 15 bit counter is used to implement the envelope rates, in effect -// dividing the clock to the envelope counter by the currently selected rate -// period. -// In addition, another counter is used to implement the exponential envelope -// decay, in effect further dividing the clock to the envelope counter. -// The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope -// counter values 255, 93, 54, 26, 14, 6, respectively. -// ---------------------------------------------------------------------------- -class EnvelopeGeneratorFP -{ -public: - EnvelopeGeneratorFP(); - - enum State { ATTACK, DECAY_SUSTAIN, RELEASE }; - - RESID_INLINE void clock(); - void reset(); - - void writeCONTROL_REG(reg8); - void writeATTACK_DECAY(reg8); - void writeSUSTAIN_RELEASE(reg8); - reg8 readENV(); - - // 8-bit envelope output. - RESID_INLINE reg8 output(); - -protected: - void update_rate_period(reg16 period); - - int rate_counter; - int rate_period; - reg8 exponential_counter; - reg8 exponential_counter_period; - reg8 envelope_counter; - bool hold_zero; - - reg4 attack; - reg4 decay; - reg4 sustain; - reg4 release; - - reg8 gate; - - State state; - - // Lookup table to convert from attack, decay, or release value to rate - // counter period. - static reg16 rate_counter_period[]; - - // The 16 selectable sustain levels. - static reg8 sustain_level[]; - -friend class SIDFP; -}; - - -// ---------------------------------------------------------------------------- -// SID clocking - 1 cycle. -// ---------------------------------------------------------------------------- -RESID_INLINE -void EnvelopeGeneratorFP::clock() -{ - if (++ rate_counter != rate_period) - return; - - rate_counter = 0; - - // The first envelope step in the attack state also resets the exponential - // counter. This has been verified by sampling ENV3. - // - if (state == ATTACK || ++exponential_counter == exponential_counter_period) - { - exponential_counter = 0; - - // Check whether the envelope counter is frozen at zero. - if (hold_zero) { - return; - } - - switch (state) { - case ATTACK: - // The envelope counter can flip from 0xff to 0x00 by changing state to - // release, then to attack. The envelope counter is then frozen at - // zero; to unlock this situation the state must be changed to release, - // then to attack. This has been verified by sampling ENV3. - // - ++envelope_counter &= 0xff; - if (envelope_counter == 0xff) { - state = DECAY_SUSTAIN; - update_rate_period(rate_counter_period[decay]); - } - break; - case DECAY_SUSTAIN: - if (envelope_counter != sustain_level[sustain]) { - --envelope_counter; - } - break; - case RELEASE: - // The envelope counter can flip from 0x00 to 0xff by changing state to - // attack, then to release. The envelope counter will then continue - // counting down in the release state. - // This has been verified by sampling ENV3. - // NB! The operation below requires two's complement integer. - // - --envelope_counter &= 0xff; - break; - } - - // Check for change of exponential counter period. - switch (envelope_counter) { - case 0xff: - exponential_counter_period = 1; - break; - case 0x5d: - exponential_counter_period = 2; - break; - case 0x36: - exponential_counter_period = 4; - break; - case 0x1a: - exponential_counter_period = 8; - break; - case 0x0e: - exponential_counter_period = 16; - break; - case 0x06: - exponential_counter_period = 30; - break; - case 0x00: - exponential_counter_period = 1; - - // When the envelope counter is changed to zero, it is frozen at zero. - // This has been verified by sampling ENV3. - hold_zero = true; - break; - } - } -} - -// ---------------------------------------------------------------------------- -// Read the envelope generator output. -// ---------------------------------------------------------------------------- -RESID_INLINE -reg8 EnvelopeGeneratorFP::output() -{ - return envelope_counter; -} - -#endif // not __ENVELOPE_H__ diff --git a/src/sound/resid-fp/extfilt.cc b/src/sound/resid-fp/extfilt.cc deleted file mode 100644 index 777a23ee39..0000000000 --- a/src/sound/resid-fp/extfilt.cc +++ /dev/null @@ -1,94 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#define __EXTFILT_CC__ -#include "extfilt.h" - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -ExternalFilterFP::ExternalFilterFP() -{ - reset(); - enable_filter(true); - set_chip_model(MOS6581FP); - set_clock_frequency(1e6f); - set_sampling_parameter(15915.6f); -} - - -// ---------------------------------------------------------------------------- -// Enable filter. -// ---------------------------------------------------------------------------- -void ExternalFilterFP::enable_filter(bool enable) -{ - enabled = enable; -} - -// ---------------------------------------------------------------------------- -// Setup of the external filter sampling parameters. -// ---------------------------------------------------------------------------- -void ExternalFilterFP::set_clock_frequency(float clock) -{ - clock_frequency = clock; - _set_sampling_parameter(); -} - -void ExternalFilterFP::set_sampling_parameter(float freq) -{ - pass_frequency = freq; - _set_sampling_parameter(); -} - -void ExternalFilterFP::_set_sampling_parameter() -{ - // Low-pass: R = 10kOhm, C = 1000pF; w0l = 1/RC = 1/(1e4*1e-9) = 100000 - // High-pass: R = 1kOhm, C = 10uF; w0h = 1/RC = 1/(1e3*1e-5) = 100 - w0hp = 100.f / clock_frequency; - w0lp = pass_frequency * 2.f * M_PI_f / clock_frequency; -} - -// ---------------------------------------------------------------------------- -// Set chip model. -// ---------------------------------------------------------------------------- -void ExternalFilterFP::set_chip_model(chip_model model) -{ - if (model == MOS6581FP) { - // Approximate the DC output level to be removed if the external - // filter is turned off. (0x800 - wave_zero + voice DC) * maxenv * voices - // - extin offset... - mixer_DC = (-0x600 + 0x800) * 0xff * 3 - 0x20000; - } - else { - // No DC offsets in the MOS8580. - mixer_DC = 0; - } -} - - -// ---------------------------------------------------------------------------- -// SID reset. -// ---------------------------------------------------------------------------- -void ExternalFilterFP::reset() -{ - // State of filter. - Vlp = 0; - Vhp = 0; - Vo = 0; -} diff --git a/src/sound/resid-fp/extfilt.h b/src/sound/resid-fp/extfilt.h deleted file mode 100644 index b0e04d3b86..0000000000 --- a/src/sound/resid-fp/extfilt.h +++ /dev/null @@ -1,120 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#ifndef __EXTFILT_H__ -#define __EXTFILT_H__ - -#include - -#include "siddefs-fp.h" - -// ---------------------------------------------------------------------------- -// The audio output stage in a Commodore 64 consists of two STC networks, -// a low-pass filter with 3-dB frequency 16kHz followed by a high-pass -// filter with 3-dB frequency 16Hz (the latter provided an audio equipment -// input impedance of 1kOhm). -// The STC networks are connected with a BJT supposedly meant to act as -// a unity gain buffer, which is not really how it works. A more elaborate -// model would include the BJT, however DC circuit analysis yields BJT -// base-emitter and emitter-base impedances sufficiently low to produce -// additional low-pass and high-pass 3dB-frequencies in the order of hundreds -// of kHz. This calls for a sampling frequency of several MHz, which is far -// too high for practical use. -// ---------------------------------------------------------------------------- -class ExternalFilterFP -{ -public: - ExternalFilterFP(); - - void enable_filter(bool enable); - void set_sampling_parameter(float pass_freq); - void set_chip_model(chip_model model); - void set_clock_frequency(float); - - RESID_INLINE void clock(float Vi); - void reset(); - - // Audio output (20 bits). - RESID_INLINE float output(); - -private: - void _set_sampling_parameter(); - void nuke_denormals(); - - // Filter enabled. - bool enabled; - - // Maximum mixer DC offset. - float mixer_DC; - - // Relevant clocks - float clock_frequency, pass_frequency; - - // State of filters. - float Vlp; // lowpass - float Vhp; // highpass - float Vo; - - // Cutoff frequencies. - float w0lp; - float w0hp; - -friend class SIDFP; -}; - -// ---------------------------------------------------------------------------- -// SID clocking - 1 cycle. -// ---------------------------------------------------------------------------- -RESID_INLINE -void ExternalFilterFP::clock(float Vi) -{ - // This is handy for testing. - if (! enabled) { - // Remove maximum DC level since there is no filter to do it. - Vlp = Vhp = 0.f; - Vo = Vi - mixer_DC; - return; - } - - float dVlp = w0lp * (Vi - Vlp); - float dVhp = w0hp * (Vlp - Vhp); - Vo = Vlp - Vhp; - Vlp += dVlp; - Vhp += dVhp; -} - -// ---------------------------------------------------------------------------- -// Audio output (19.5 bits). -// ---------------------------------------------------------------------------- -RESID_INLINE -float ExternalFilterFP::output() -{ - return Vo; -} - -RESID_INLINE -void ExternalFilterFP::nuke_denormals() -{ - if (Vhp > -1e-12f && Vhp < 1e-12f) - Vhp = 0; - if (Vlp > -1e-12f && Vlp < 1e-12f) - Vlp = 0; -} - -#endif // not __EXTFILT_H__ diff --git a/src/sound/resid-fp/filter.cc b/src/sound/resid-fp/filter.cc deleted file mode 100644 index c327fadecc..0000000000 --- a/src/sound/resid-fp/filter.cc +++ /dev/null @@ -1,194 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- -// Filter distortion code written by Antti S. Lankila 2007 - 2008. - -#define __FILTER_CC__ -#include "filter.h" -#include "sid.h" - -#ifndef HAVE_LOGF_PROTOTYPE -extern float logf(float val); -#endif - -#ifndef HAVE_EXPF_PROTOTYPE -extern float expf(float val); -#endif - -#ifndef HAVE_LOGF -float logf(float val) -{ - return (float)log((double)val); -} -#endif - -#ifndef HAVE_EXPF -float expf(float val) -{ - return (float)exp((double)val); -} -#endif - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -FilterFP::FilterFP() -{ - model = (chip_model) 0; // neither 6581/8580; init time only - enable_filter(true); - /* approximate; sid.cc calls us when set_sampling_parameters() occurs. */ - set_clock_frequency(1e6f); - /* these parameters are a work-in-progress. */ - set_distortion_properties(2.5e-3f, 1536.f, 1e-4f); - /* sound similar to alankila6581r4ar3789 */ - set_type3_properties(1.40e6f, 1.47e8f, 1.0059f, 1.55e4f); - /* sound similar to trurl8580r5_3691 */ - set_type4_properties(6.55f, 20.f); - reset(); - set_chip_model(MOS6581FP); -} - - -// ---------------------------------------------------------------------------- -// Enable filter. -// ---------------------------------------------------------------------------- -void FilterFP::enable_filter(bool enable) -{ - enabled = enable; -} - - -// ---------------------------------------------------------------------------- -// Set chip model. -// ---------------------------------------------------------------------------- -void FilterFP::set_chip_model(chip_model model) -{ - this->model = model; - set_Q(); - set_w0(); -} - -/* dist_CT eliminates 1/x at hot spot */ -void FilterFP::set_clock_frequency(float clock) { - clock_frequency = clock; - calculate_helpers(); -} - -void FilterFP::set_distortion_properties(float r, float p, float cft) -{ - distortion_rate = r; - distortion_point = p; - /* baseresistance is used to determine material resistivity later */ - distortion_cf_threshold = cft; - calculate_helpers(); -} - -void FilterFP::set_type4_properties(float k, float b) -{ - type4_k = k; - type4_b = b; -} - -void FilterFP::set_type3_properties(float br, float o, float s, float mfr) -{ - type3_baseresistance = br; - type3_offset = o; - type3_steepness = -logf(s); /* s^x to e^(x*ln(s)), 1/e^x == e^-x. */ - type3_minimumfetresistance = mfr; -} - -void FilterFP::calculate_helpers() -{ - if (clock_frequency != 0.f) - distortion_CT = 1.f / (sidcaps_6581 * clock_frequency); - set_w0(); -} - -// ---------------------------------------------------------------------------- -// SID reset. -// ---------------------------------------------------------------------------- -void FilterFP::reset() -{ - fc = 0; - res = filt = voice3off = hp_bp_lp = 0; - vol = 0; - volf = Vhp = Vbp = Vlp = 0; - set_w0(); - set_Q(); -} - -// ---------------------------------------------------------------------------- -// Register functions. -// ---------------------------------------------------------------------------- -void FilterFP::writeFC_LO(reg8 fc_lo) -{ - fc = (fc & 0x7f8) | (fc_lo & 0x007); - set_w0(); -} - -void FilterFP::writeFC_HI(reg8 fc_hi) -{ - fc = ((fc_hi << 3) & 0x7f8) | (fc & 0x007); - set_w0(); -} - -void FilterFP::writeRES_FILT(reg8 res_filt) -{ - res = (res_filt >> 4) & 0x0f; - set_Q(); - - filt = res_filt & 0x0f; -} - -void FilterFP::writeMODE_VOL(reg8 mode_vol) -{ - voice3off = mode_vol & 0x80; - - hp_bp_lp = (mode_vol >> 4) & 0x07; - - vol = mode_vol & 0x0f; - volf = (float) vol / 15.f; -} - -// Set filter cutoff frequency. -void FilterFP::set_w0() -{ - if (model == MOS6581FP) { - /* div once by extra kinkiness because I fitted the type3 eq with that variant. */ - float type3_fc_kink = SIDFP::kinked_dac(fc, kinkiness, 11) / kinkiness; - type3_fc_kink_exp = type3_offset * expf(type3_fc_kink * type3_steepness); - if (distortion_rate != 0.f) { - type3_fc_distortion_offset_hp = (distortion_point - type3_fc_kink) * (0.5f) / distortion_rate; - type3_fc_distortion_offset_bp = type3_fc_distortion_offset_hp; - } - else { - type3_fc_distortion_offset_bp = 9e9f; - type3_fc_distortion_offset_hp = 9e9f; - } - } - if (model == MOS8580FP) { - type4_w0_cache = type4_w0(); - } -} - -// Set filter resonance. -void FilterFP::set_Q() -{ - float Q = res / 15.f; - _1_div_Q = 1.f / (0.707f + Q * 1.5f); -} diff --git a/src/sound/resid-fp/filter.h b/src/sound/resid-fp/filter.h deleted file mode 100644 index 9ca2545642..0000000000 --- a/src/sound/resid-fp/filter.h +++ /dev/null @@ -1,383 +0,0 @@ -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- -// Filter distortion code written by Antti S. Lankila 2007 - 2008. - -#ifndef __FILTER_H__ -#define __FILTER_H__ - -#include -#include "siddefs-fp.h" - -// ---------------------------------------------------------------------------- -// The SID filter is modeled with a two-integrator-loop biquadratic filter, -// which has been confirmed by Bob Yannes to be the actual circuit used in -// the SID chip. -// -// Measurements show that excellent emulation of the SID filter is achieved, -// except when high resonance is combined with high sustain levels. -// In this case the SID op-amps are performing less than ideally and are -// causing some peculiar behavior of the SID filter. This however seems to -// have more effect on the overall amplitude than on the color of the sound. -// -// The theory for the filter circuit can be found in "Microelectric Circuits" -// by Adel S. Sedra and Kenneth C. Smith. -// The circuit is modeled based on the explanation found there except that -// an additional inverter is used in the feedback from the bandpass output, -// allowing the summer op-amp to operate in single-ended mode. This yields -// inverted filter outputs with levels independent of Q, which corresponds with -// the results obtained from a real SID. -// -// We have been able to model the summer and the two integrators of the circuit -// to form components of an IIR filter. -// Vhp is the output of the summer, Vbp is the output of the first integrator, -// and Vlp is the output of the second integrator in the filter circuit. -// -// According to Bob Yannes, the active stages of the SID filter are not really -// op-amps. Rather, simple NMOS inverters are used. By biasing an inverter -// into its region of quasi-linear operation using a feedback resistor from -// input to output, a MOS inverter can be made to act like an op-amp for -// small signals centered around the switching threshold. -// -// Qualified guesses at SID filter schematics are depicted below. -// -// SID filter -// ---------- -// -// ----------------------------------------------- -// | | -// | ---Rq-- | -// | | | | -// | --------------|--R-----[A>--|--R-----[A>--| -// | | | | -// vi -----R1-- | | | -// -// vhp vbp vlp -// -// -// vi - input voltage -// vhp - highpass output -// vbp - bandpass output -// vlp - lowpass output -// [A> - op-amp -// R1 - summer resistor -// Rq - resistor array controlling resonance (4 resistors) -// R - NMOS FET voltage controlled resistor controlling cutoff frequency -// Rs - shunt resitor -// C - capacitor -// -// -// -// SID integrator -// -------------- -// -// V+ -// -// | -// | -// -----| -// | | -// | ||-- -// -|| -// ---C--- ||-> -// | | | -// |---Rs-----------|---- vo -// | | -// | ||-- -// vi ---- -----|------------|| -// | ^ | ||-> -// |___| | | -// ----- | | -// | | | -// |---R2-- | -// | -// R1 V- -// | -// | -// -// Vw -// -// ---------------------------------------------------------------------------- -class FilterFP -{ -public: - FilterFP(); - - void enable_filter(bool enable); - void set_chip_model(chip_model model); - void set_distortion_properties(float, float, float); - void set_type3_properties(float, float, float, float); - void set_type4_properties(float, float); - void set_clock_frequency(float); - - RESID_INLINE - float clock(float voice1, float voice2, float voice3, - float ext_in); - void reset(); - - // Write registers. - void writeFC_LO(reg8); - void writeFC_HI(reg8); - void writeRES_FILT(reg8); - void writeMODE_VOL(reg8); - -private: - void set_Q(); - void set_w0(); - float type3_w0(const float source, const float offset); - float type4_w0(); - void calculate_helpers(); - void nuke_denormals(); - - // Filter enabled. - bool enabled; - - // 6581/8580 filter model (XXX: we should specialize in separate classes) - chip_model model; - - // Filter cutoff frequency. - reg12 fc; - - // Filter resonance. - reg8 res; - - // Selects which inputs to route through filter. - reg8 filt; - - // Switch voice 3 off. - reg8 voice3off; - - // Highpass, bandpass, and lowpass filter modes. - reg8 hp_bp_lp; - - // Output master volume. - reg4 vol; - float volf; /* avoid integer-to-float conversion at output */ - - // clock - float clock_frequency; - - /* Distortion params for Type3 */ - float distortion_rate, distortion_point, distortion_cf_threshold; - - /* Type3 params. */ - float type3_baseresistance, type3_offset, type3_steepness, type3_minimumfetresistance; - - /* Type4 params */ - float type4_k, type4_b; - - // State of filter. - float Vhp, Vbp, Vlp; - - /* Resonance/Distortion/Type3/Type4 helpers. */ - float type4_w0_cache, _1_div_Q, type3_fc_kink_exp, distortion_CT, - type3_fc_distortion_offset_bp, type3_fc_distortion_offset_hp; - -friend class SIDFP; -}; - -// ---------------------------------------------------------------------------- -// Inline functions. -// The following functions are defined inline because they are called every -// time a sample is calculated. -// ---------------------------------------------------------------------------- - -/* kinkiness of DAC: - * some chips have more, some less. We should make this tunable. */ -const float kinkiness = 0.966f; -const float sidcaps_6581 = 470e-12f; -const float outputleveldifference_lp_bp = 1.4f; -const float outputleveldifference_bp_hp = 1.2f; - -RESID_INLINE -static float fastexp(float val) { - typedef union { - int i; - float f; - } conv; - - conv tmp; - - /* single precision fp has 1 + 8 + 23 bits, exponent bias is 127. - * It therefore follows that we need to shift left by 23 bits, and to - * calculate exp(x) instead of pow(2, x) we divide the power by ln(2). */ - const float a = (1 << 23) / M_LN2_f; - /* The other factor corrects for the exponent bias so that 2^0 = 1. */ - const float b = (1 << 23) * 127; - /* According to "A Fast, Compact Approximation of the Exponential Function" - * by Nicol N. Schraudolph, 60801.48 yields the minimum RMS error for the - * piecewise-linear approximation when using doubles (20 bits residual). - * We have 23 bits, so we scale this value by 8. */ - const float c = 60801.48f * 8.f + 0.5f; - - /* Parenthesis are important: C standard disallows folding subtraction. - * Unfortunately GCC appears to generate a write to memory rather than - * handle this conversion entirely in registers. */ - tmp.i = (int)(a * val + (b - c)); - return tmp.f; -} - -RESID_INLINE -float FilterFP::type3_w0(const float source, const float distoffset) -{ - /* The distortion appears to be the result of MOSFET entering saturation - * mode. The conductance of a FET is proportional to: - * - * ohmic = 2 * (Vgs - Vt) * Vds - Vds^2 - * saturation = (Vgs - Vt)^2 - * - * The FET switches to saturation mode when Vgs - Vt < Vds. - * - * In the circuit, the Vgs is mixed with the Vds signal, which gives - * (Vgs + Vds) / 2 as the gate voltage. Doing the substitutions we get: - * - * ohmic = 2 * ((Vgs + Vds) / 2 - Vt) * Vds - Vds^2 = (Vgs - Vt) * Vds - * saturation = ((Vgs + Vds) / 2 - Vt)^2 - * - * Therefore: once the Vds crosses a threshold given by the gate and - * threshold FET conductance begins to increase faster. The exact shape - * for this effect is a parabola. - * - * The scaling term here tries to match the FC control level with - * the signal level in simulation. On the chip, the FC control is - * biased by forcing its highest DAC bit in the 1 position, thus - * limiting the electrical range to half. Therefore one can guess that - * the real FC range is half of the full voice range. - * - * On the simulation, FC goes to 2047 and the voices to 4095 * 255. - * If the FC control was intact, then the scaling factor would be - * 1/512. (Simulation voices are 512 times "louder" intrinsically.) - * As the real chip's FC has reduced range, the scaling required to - * match levels is 1/256. */ - - float fetresistance = type3_fc_kink_exp; - if (source > distoffset) { - const float dist = source - distoffset; - fetresistance *= fastexp(dist * type3_steepness * distortion_rate); - } - const float dynamic_resistance = type3_minimumfetresistance + fetresistance; - - /* 2 parallel resistors */ - const float _1_div_resistance = (type3_baseresistance + dynamic_resistance) / (type3_baseresistance * dynamic_resistance); - /* 1.f / (clock * caps * resistance) */ - return distortion_CT * _1_div_resistance; -} - -RESID_INLINE -float FilterFP::type4_w0() -{ - const float freq = type4_k * fc + type4_b; - return 2.f * M_PI_f * freq / clock_frequency; -} - -// ---------------------------------------------------------------------------- -// SID clocking - 1 cycle. -// ---------------------------------------------------------------------------- -RESID_INLINE -float FilterFP::clock(float voice1, - float voice2, - float voice3, - float ext_in) -{ - /* Avoid denormal numbers by using small offsets from 0 */ - float Vi = 0.f, Vnf = 0.f, Vf = 0.f; - - // Route voices into or around filter. - ((filt & 1) ? Vi : Vnf) += voice1; - ((filt & 2) ? Vi : Vnf) += voice2; - // NB! Voice 3 is not silenced by voice3off if it is routed through - // the filter. - if (filt & 4) - Vi += voice3; - else if (! voice3off) - Vnf += voice3; - ((filt & 8) ? Vi : Vnf) += ext_in; - - if (! enabled) - return (Vnf - Vi) * volf; - - if (hp_bp_lp & 1) - Vf += Vlp; - if (hp_bp_lp & 2) - Vf += Vbp; - if (hp_bp_lp & 4) - Vf += Vhp; - - if (model == MOS6581FP) { - float diff1, diff2; - - Vhp = Vbp * _1_div_Q * (1.f/outputleveldifference_bp_hp) - Vlp * (1.f/outputleveldifference_bp_hp) - Vi * 0.5f; - - /* the input summer mixing, or something like it... */ - diff1 = (Vlp - Vbp) * distortion_cf_threshold; - diff2 = (Vhp - Vbp) * distortion_cf_threshold; - Vlp -= diff1; - Vbp += diff1; - Vbp += diff2; - Vhp -= diff2; - - /* Model output strip mixing. Doing it now that HP state - * variable modifying still makes some difference. - * (Phase error, though.) */ - if (hp_bp_lp & 1) - Vlp += (Vf + Vnf - Vlp) * distortion_cf_threshold; - if (hp_bp_lp & 2) - Vbp += (Vf + Vnf - Vbp) * distortion_cf_threshold; - if (hp_bp_lp & 4) - Vhp += (Vf + Vnf - Vhp) * distortion_cf_threshold; - - /* Simulating the exponential VCR that the FET block is... */ - Vlp -= Vbp * type3_w0(Vbp, type3_fc_distortion_offset_bp); - Vbp -= Vhp * type3_w0(Vhp, type3_fc_distortion_offset_hp) * outputleveldifference_bp_hp; - - /* Tuned based on Fred Gray's Break Thru. It is probably not a hard - * discontinuity but a saturation effect... */ - if (Vnf > 3.2e6f) - Vnf = 3.2e6f; - - Vf += Vnf + Vlp * (outputleveldifference_lp_bp - 1.f); - } else { - /* On the 8580, BP appears mixed in phase with the rest. */ - Vhp = -Vbp * _1_div_Q - Vlp - Vi; - Vlp += Vbp * type4_w0_cache; - Vbp += Vhp * type4_w0_cache; - - Vf += Vnf; - } - - return Vf * volf; -} - -RESID_INLINE -void FilterFP::nuke_denormals() -{ - /* We could use the flush-to-zero flag or denormals-are-zero on systems - * where compiling with -msse and -mfpmath=sse is acceptable. Since this - * doesn't include general VICE builds, we do this instead. */ - if (Vbp > -1e-12f && Vbp < 1e-12f) - Vbp = 0; - if (Vlp > -1e-12f && Vlp < 1e-12f) - Vlp = 0; -} - -#endif // not __FILTER_H__ diff --git a/src/sound/resid-fp/pot.cc b/src/sound/resid-fp/pot.cc deleted file mode 100644 index 4cd85a5c3f..0000000000 --- a/src/sound/resid-fp/pot.cc +++ /dev/null @@ -1,26 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "pot.h" - -reg8 PotentiometerFP::readPOT() -{ - // NB! Not modeled. - return 0xff; -} diff --git a/src/sound/resid-fp/pot.h b/src/sound/resid-fp/pot.h deleted file mode 100644 index e1deeabdab..0000000000 --- a/src/sound/resid-fp/pot.h +++ /dev/null @@ -1,31 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#ifndef __POT_H__ -#define __POT_H__ - -#include "siddefs-fp.h" - -class PotentiometerFP -{ -public: - reg8 readPOT(); -}; - -#endif diff --git a/src/sound/resid-fp/resample/Resampler.h b/src/sound/resid-fp/resample/Resampler.h new file mode 100644 index 0000000000..904f65458e --- /dev/null +++ b/src/sound/resid-fp/resample/Resampler.h @@ -0,0 +1,86 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef RESAMPLER_H +#define RESAMPLER_H + +#include + +#include "../sidcxx11.h" + +#include "../siddefs-fp.h" + +namespace reSIDfp +{ + +/** + * Abstraction of a resampling process. Given enough input, produces output. + * Constructors take additional arguments that configure these objects. + */ +class Resampler +{ +protected: + inline short softClip(int x) const + { + constexpr int threshold = 28000; + if (likely(x < threshold)) + return x; + + constexpr double t = threshold / 32768.; + constexpr double a = 1. - t; + constexpr double b = 1. / a; + + double value = static_cast(x - threshold) / 32768.; + value = t + a * tanh(b * value); + return static_cast(value * 32768.); + } + + virtual int output() const = 0; + + Resampler() {} + +public: + virtual ~Resampler() {} + + /** + * Input a sample into resampler. Output "true" when resampler is ready with new sample. + * + * @param sample input sample + * @return true when a sample is ready + */ + virtual bool input(int sample) = 0; + + /** + * Output a sample from resampler. + * + * @return resampled sample + */ + short getOutput() const + { + return softClip(output()); + } + + virtual void reset() = 0; +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/resample/SincResampler.cpp b/src/sound/resid-fp/resample/SincResampler.cpp new file mode 100644 index 0000000000..df7d8af833 --- /dev/null +++ b/src/sound/resid-fp/resample/SincResampler.cpp @@ -0,0 +1,397 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2020 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "SincResampler.h" + +#include +#include +#include +#include +#include + +#include "../siddefs-fp.h" + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_EMMINTRIN_H +# include +#elif defined HAVE_MMINTRIN_H +# include +#elif defined(HAVE_ARM_NEON_H) +# include +#endif + +namespace reSIDfp +{ + +typedef std::map fir_cache_t; + +/// Cache for the expensive FIR table computation results. +fir_cache_t FIR_CACHE; + +/// Maximum error acceptable in I0 is 1e-6, or ~96 dB. +const double I0E = 1e-6; + +const int BITS = 16; + +/** + * Compute the 0th order modified Bessel function of the first kind. + * This function is originally from resample-1.5/filterkit.c by J. O. Smith. + * It is used to build the Kaiser window for resampling. + * + * @param x evaluate I0 at x + * @return value of I0 at x. + */ +double I0(double x) +{ + double sum = 1.; + double u = 1.; + double n = 1.; + const double halfx = x / 2.; + + do + { + const double temp = halfx / n; + u *= temp * temp; + sum += u; + n += 1.; + } + while (u >= I0E * sum); + + return sum; +} + +/** + * Calculate convolution with sample and sinc. + * + * @param a sample buffer input + * @param b sinc buffer + * @param bLength length of the sinc buffer + * @return convolved result + */ +int convolve(const short* a, const short* b, int bLength) +{ +#ifdef HAVE_EMMINTRIN_H + int out = 0; + + const uintptr_t offset = (uintptr_t)(a) & 0x0f; + + // check for aligned accesses + if (offset == ((uintptr_t)(b) & 0x0f)) + { + if (offset) + { + const int l = (0x10 - offset)/2; + + for (int i = 0; i < l; i++) + { + out += *a++ * *b++; + } + + bLength -= offset; + } + + __m128i acc = _mm_setzero_si128(); + + const int n = bLength / 8; + + for (int i = 0; i < n; i++) + { + const __m128i tmp = _mm_madd_epi16(*(__m128i*)a, *(__m128i*)b); + acc = _mm_add_epi16(acc, tmp); + a += 8; + b += 8; + } + + __m128i vsum = _mm_add_epi32(acc, _mm_srli_si128(acc, 8)); + vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4)); + out += _mm_cvtsi128_si32(vsum); + + bLength &= 7; + } +#elif defined HAVE_MMINTRIN_H + __m64 acc = _mm_setzero_si64(); + + const int n = bLength / 4; + + for (int i = 0; i < n; i++) + { + const __m64 tmp = _mm_madd_pi16(*(__m64*)a, *(__m64*)b); + acc = _mm_add_pi16(acc, tmp); + a += 4; + b += 4; + } + + int out = _mm_cvtsi64_si32(acc) + _mm_cvtsi64_si32(_mm_srli_si64(acc, 32)); + _mm_empty(); + + bLength &= 3; +#elif defined(HAVE_ARM_NEON_H) +#if (defined(__arm64__) && defined(__APPLE__)) || defined(__aarch64__) + int32x4_t acc1Low = vdupq_n_s32(0); + int32x4_t acc1High = vdupq_n_s32(0); + int32x4_t acc2Low = vdupq_n_s32(0); + int32x4_t acc2High = vdupq_n_s32(0); + + const int n = bLength / 16; + + for (int i = 0; i < n; i++) + { + int16x8_t v11 = vld1q_s16(a); + int16x8_t v12 = vld1q_s16(a + 8); + int16x8_t v21 = vld1q_s16(b); + int16x8_t v22 = vld1q_s16(b + 8); + + acc1Low = vmlal_s16(acc1Low, vget_low_s16(v11), vget_low_s16(v21)); + acc1High = vmlal_high_s16(acc1High, v11, v21); + acc2Low = vmlal_s16(acc2Low, vget_low_s16(v12), vget_low_s16(v22)); + acc2High = vmlal_high_s16(acc2High, v12, v22); + + a += 16; + b += 16; + } + + bLength &= 15; + + if (bLength >= 8) + { + int16x8_t v1 = vld1q_s16(a); + int16x8_t v2 = vld1q_s16(b); + + acc1Low = vmlal_s16(acc1Low, vget_low_s16(v1), vget_low_s16(v2)); + acc1High = vmlal_high_s16(acc1High, v1, v2); + + a += 8; + b += 8; + } + + bLength &= 7; + + if (bLength >= 4) + { + int16x4_t v1 = vld1_s16(a); + int16x4_t v2 = vld1_s16(b); + + acc1Low = vmlal_s16(acc1Low, v1, v2); + + a += 4; + b += 4; + } + + int32x4_t accSumsNeon = vaddq_s32(acc1Low, acc1High); + accSumsNeon = vaddq_s32(accSumsNeon, acc2Low); + accSumsNeon = vaddq_s32(accSumsNeon, acc2High); + + int out = vaddvq_s32(accSumsNeon); + + bLength &= 3; +#else + int32x4_t acc = vdupq_n_s32(0); + + const int n = bLength / 4; + + for (int i = 0; i < n; i++) + { + const int16x4_t h_vec = vld1_s16(a); + const int16x4_t x_vec = vld1_s16(b); + acc = vmlal_s16(acc, h_vec, x_vec); + a += 4; + b += 4; + } + + int out = vgetq_lane_s32(acc, 0) + + vgetq_lane_s32(acc, 1) + + vgetq_lane_s32(acc, 2) + + vgetq_lane_s32(acc, 3); + + bLength &= 3; +#endif +#else + int out = 0; +#endif + + for (int i = 0; i < bLength; i++) + { + out += *a++ * *b++; + } + + return (out + (1 << 14)) >> 15; +} + +int SincResampler::fir(int subcycle) +{ + // Find the first of the nearest fir tables close to the phase + int firTableFirst = (subcycle * firRES >> 10); + const int firTableOffset = (subcycle * firRES) & 0x3ff; + + // Find firN most recent samples, plus one extra in case the FIR wraps. + int sampleStart = sampleIndex - firN + RINGSIZE - 1; + + const int v1 = convolve(sample + sampleStart, (*firTable)[firTableFirst], firN); + + // Use next FIR table, wrap around to first FIR table using + // previous sample. + if (unlikely(++firTableFirst == firRES)) + { + firTableFirst = 0; + ++sampleStart; + } + + const int v2 = convolve(sample + sampleStart, (*firTable)[firTableFirst], firN); + + // Linear interpolation between the sinc tables yields good + // approximation for the exact value. + return v1 + (firTableOffset * (v2 - v1) >> 10); +} + +SincResampler::SincResampler(double clockFrequency, double samplingFrequency, double highestAccurateFrequency) : + sampleIndex(0), + cyclesPerSample(static_cast(clockFrequency / samplingFrequency * 1024.)), + sampleOffset(0), + outputValue(0) +{ + // 16 bits -> -96dB stopband attenuation. + const double A = -20. * log10(1.0 / (1 << BITS)); + // A fraction of the bandwidth is allocated to the transition band, which we double + // because we design the filter to transition halfway at nyquist. + const double dw = (1. - 2.*highestAccurateFrequency / samplingFrequency) * M_PI * 2.; + + // For calculation of beta and N see the reference for the kaiserord + // function in the MATLAB Signal Processing Toolbox: + // http://www.mathworks.com/help/signal/ref/kaiserord.html + const double beta = 0.1102 * (A - 8.7); + const double I0beta = I0(beta); + const double cyclesPerSampleD = clockFrequency / samplingFrequency; + + { + // The filter order will maximally be 124 with the current constraints. + // N >= (96.33 - 7.95)/(2 * pi * 2.285 * (maxfreq - passbandfreq) >= 123 + // The filter order is equal to the number of zero crossings, i.e. + // it should be an even number (sinc is symmetric with respect to x = 0). + int N = static_cast((A - 7.95) / (2.285 * dw) + 0.5); + N += N & 1; + + // The filter length is equal to the filter order + 1. + // The filter length must be an odd number (sinc is symmetric with respect to + // x = 0). + firN = static_cast(N * cyclesPerSampleD) + 1; + firN |= 1; + + // Check whether the sample ring buffer would overflow. + assert(firN < RINGSIZE); + + // Error is bounded by err < 1.234 / L^2, so L = sqrt(1.234 / (2^-16)) = sqrt(1.234 * 2^16). + firRES = static_cast(ceil(sqrt(1.234 * (1 << BITS)) / cyclesPerSampleD)); + + // firN*firRES represent the total resolution of the sinc sampling. JOS + // recommends a length of 2^BITS, but we don't quite use that good a filter. + // The filter test program indicates that the filter performs well, though. + } + + // Create the map key + std::ostringstream o; + o << firN << "," << firRES << "," << cyclesPerSampleD; + const std::string firKey = o.str(); + fir_cache_t::iterator lb = FIR_CACHE.lower_bound(firKey); + + // The FIR computation is expensive and we set sampling parameters often, but + // from a very small set of choices. Thus, caching is used to speed initialization. + if (lb != FIR_CACHE.end() && !(FIR_CACHE.key_comp()(firKey, lb->first))) + { + firTable = &(lb->second); + } + else + { + // Allocate memory for FIR tables. + matrix_t tempTable(firRES, firN); +#ifdef HAVE_CXX11 + firTable = &(FIR_CACHE.emplace_hint(lb, fir_cache_t::value_type(firKey, tempTable))->second); +#else + firTable = &(FIR_CACHE.insert(lb, fir_cache_t::value_type(firKey, tempTable))->second); +#endif + + // The cutoff frequency is midway through the transition band, in effect the same as nyquist. + const double wc = M_PI; + + // Calculate the sinc tables. + const double scale = 32768.0 * wc / cyclesPerSampleD / M_PI; + + // we're not interested in the fractional part + // so use int division before converting to double + const int tmp = firN / 2; + const double firN_2 = static_cast(tmp); + + for (int i = 0; i < firRES; i++) + { + const double jPhase = (double) i / firRES + firN_2; + + for (int j = 0; j < firN; j++) + { + const double x = j - jPhase; + + const double xt = x / firN_2; + const double kaiserXt = fabs(xt) < 1. ? I0(beta * sqrt(1. - xt * xt)) / I0beta : 0.; + + const double wt = wc * x / cyclesPerSampleD; + const double sincWt = fabs(wt) >= 1e-8 ? sin(wt) / wt : 1.; + + (*firTable)[i][j] = static_cast(scale * sincWt * kaiserXt); + } + } + } +} + +bool SincResampler::input(int input) +{ + bool ready = false; + + /* + * Clip the input as it may overflow the 16 bit range. + * + * Approximate measured input ranges: + * 6581: [-24262,+25080] (Kawasaki_Synthesizer_Demo) + * 8580: [-21514,+35232] (64_Forever, Drum_Fool) + */ + sample[sampleIndex] = sample[sampleIndex + RINGSIZE] = softClip(input); + sampleIndex = (sampleIndex + 1) & (RINGSIZE - 1); + + if (sampleOffset < 1024) + { + outputValue = fir(sampleOffset); + ready = true; + sampleOffset += cyclesPerSample; + } + + sampleOffset -= 1024; + + return ready; +} + +void SincResampler::reset() +{ + memset(sample, 0, sizeof(sample)); + sampleOffset = 0; +} + +} // namespace reSIDfp diff --git a/src/sound/resid-fp/resample/SincResampler.h b/src/sound/resid-fp/resample/SincResampler.h new file mode 100644 index 0000000000..7502d96fda --- /dev/null +++ b/src/sound/resid-fp/resample/SincResampler.h @@ -0,0 +1,114 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2013 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SINCRESAMPLER_H +#define SINCRESAMPLER_H + +#include "Resampler.h" + +#include +#include + +#include "../array.h" + +#include "../sidcxx11.h" + +namespace reSIDfp +{ + +/** + * This is the theoretically correct (and computationally intensive) audio sample generation. + * The samples are generated by resampling to the specified sampling frequency. + * The work rate is inversely proportional to the percentage of the bandwidth + * allocated to the filter transition band. + * + * This implementation is based on the paper "A Flexible Sampling-Rate Conversion Method", + * by J. O. Smith and P. Gosset, or rather on the expanded tutorial on the + * [Digital Audio Resampling Home Page](http://www-ccrma.stanford.edu/~jos/resample/). + * + * By building shifted FIR tables with samples according to the sampling frequency, + * this implementation dramatically reduces the computational effort in the + * filter convolutions, without any loss of accuracy. + * The filter convolutions are also vectorizable on current hardware. + */ +class SincResampler final : public Resampler +{ +private: + /// Size of the ring buffer, must be a power of 2 + static const int RINGSIZE = 2048; + +private: + /// Table of the fir filter coefficients + matrix_t* firTable; + + int sampleIndex; + + /// Filter resolution + int firRES; + + /// Filter length + int firN; + + const int cyclesPerSample; + + int sampleOffset; + + int outputValue; + + short sample[RINGSIZE * 2]; + +private: + int fir(int subcycle); + +public: + /** + * Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64. + * The default end of passband frequency is pass_freq = 0.9*sample_freq/2 + * for sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample frequencies. + * + * For resampling, the ratio between the clock frequency and the sample frequency + * is limited as follows: 125*clock_freq/sample_freq < 16384 + * E.g. provided a clock frequency of ~ 1MHz, the sample frequency + * can not be set lower than ~ 8kHz. + * A lower sample frequency would make the resampling code overfill its 16k sample ring buffer. + * + * The end of passband frequency is also limited: pass_freq <= 0.9*sample_freq/2 + * + * E.g. for a 44.1kHz sampling rate the end of passband frequency is limited + * to slightly below 20kHz. This constraint ensures that the FIR table is not overfilled. + * + * @param clockFrequency System clock frequency at Hz + * @param samplingFrequency Desired output sampling rate + * @param highestAccurateFrequency + */ + SincResampler(double clockFrequency, double samplingFrequency, double highestAccurateFrequency); + + bool input(int input) override; + + int output() const override { return outputValue; } + + void reset() override; +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/resample/TwoPassSincResampler.h b/src/sound/resid-fp/resample/TwoPassSincResampler.h new file mode 100644 index 0000000000..81659193a7 --- /dev/null +++ b/src/sound/resid-fp/resample/TwoPassSincResampler.h @@ -0,0 +1,83 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2015 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TWOPASSSINCRESAMPLER_H +#define TWOPASSSINCRESAMPLER_H + +#include + +#include + +#include "Resampler.h" +#include "SincResampler.h" + +#include "../sidcxx11.h" + +namespace reSIDfp +{ + +/** + * Compose a more efficient SINC from chaining two other SINCs. + */ +class TwoPassSincResampler final : public Resampler +{ +private: + std::unique_ptr const s1; + std::unique_ptr const s2; + +private: + TwoPassSincResampler(double clockFrequency, double samplingFrequency, double highestAccurateFrequency, double intermediateFrequency) : + s1(new SincResampler(clockFrequency, intermediateFrequency, highestAccurateFrequency)), + s2(new SincResampler(intermediateFrequency, samplingFrequency, highestAccurateFrequency)) + {} + +public: + // Named constructor + static TwoPassSincResampler* create(double clockFrequency, double samplingFrequency, double highestAccurateFrequency) + { + // Calculation according to Laurent Ganier. It evaluates to about 120 kHz at typical settings. + // Some testing around the chosen value seems to confirm that this does work. + double const intermediateFrequency = 2. * highestAccurateFrequency + + sqrt(2. * highestAccurateFrequency * clockFrequency + * (samplingFrequency - 2. * highestAccurateFrequency) / samplingFrequency); + return new TwoPassSincResampler(clockFrequency, samplingFrequency, highestAccurateFrequency, intermediateFrequency); + } + + bool input(int sample) override + { + return s1->input(sample) && s2->input(s1->output()); + } + + int output() const override + { + return s2->output(); + } + + void reset() override + { + s1->reset(); + s2->reset(); + } +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/resample/ZeroOrderResampler.h b/src/sound/resid-fp/resample/ZeroOrderResampler.h new file mode 100644 index 0000000000..2bc80cded8 --- /dev/null +++ b/src/sound/resid-fp/resample/ZeroOrderResampler.h @@ -0,0 +1,88 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2013 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef ZEROORDER_RESAMPLER_H +#define ZEROORDER_RESAMPLER_H + +#include "Resampler.h" + +#include "../sidcxx11.h" + +namespace reSIDfp +{ + +/** + * Return sample with linear interpolation. + * + * @author Antti Lankila + */ +class ZeroOrderResampler final : public Resampler +{ + +private: + /// Last sample + int cachedSample; + + /// Number of cycles per sample + const int cyclesPerSample; + + int sampleOffset; + + /// Calculated sample + int outputValue; + +public: + ZeroOrderResampler(double clockFrequency, double samplingFrequency) : + cachedSample(0), + cyclesPerSample(static_cast(clockFrequency / samplingFrequency * 1024.)), + sampleOffset(0), + outputValue(0) {} + + bool input(int sample) override + { + bool ready = false; + + if (sampleOffset < 1024) + { + outputValue = cachedSample + (sampleOffset * (sample - cachedSample) >> 10); + ready = true; + sampleOffset += cyclesPerSample; + } + + sampleOffset -= 1024; + + cachedSample = sample; + + return ready; + } + + int output() const override { return outputValue; } + + void reset() override + { + sampleOffset = 0; + cachedSample = 0; + } +}; + +} // namespace reSIDfp + +#endif diff --git a/src/sound/resid-fp/resample/test.cpp b/src/sound/resid-fp/resample/test.cpp new file mode 100644 index 0000000000..b229e9e4dc --- /dev/null +++ b/src/sound/resid-fp/resample/test.cpp @@ -0,0 +1,91 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2012-2013 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "../siddefs-fp.h" + +#include "Resampler.h" +#include "TwoPassSincResampler.h" + +#if __cplusplus < 201103L +# define unique_ptr auto_ptr +#endif + +/** + * Simple sin waveform in, power output measurement function. + * It would be far better to use FFT. + */ +int main(int, const char*[]) +{ + const double RATE = 985248.4; + const int RINGSIZE = 2048; + + std::unique_ptr r(reSIDfp::TwoPassSincResampler::create(RATE, 48000.0, 20000.0)); + + std::map results; + clock_t start = clock(); + + for (double freq = 1000.; freq < RATE / 2.; freq *= 1.01) + { + /* prefill resampler buffer */ + int k = 0; + double omega = 2 * M_PI * freq / RATE; + + for (int j = 0; j < RINGSIZE; j ++) + { + int signal = static_cast(32768.0 * sin(k++ * omega) * sqrt(2)); + r->input(signal); + } + + int n = 0; + float pwr = 0; + + /* Now, during measurement stage, put 100 cycles of waveform through filter. */ + for (int j = 0; j < 100000; j ++) + { + int signal = static_cast(32768.0 * sin(k++ * omega) * sqrt(2)); + + if (r->input(signal)) + { + float out = r->output(); + pwr += out * out; + n += 1; + } + } + + results.insert(std::make_pair(freq, 10 * log10(pwr / n))); + } + + clock_t end = clock(); + + for (std::map::iterator it = results.begin(); it != results.end(); ++it) + { + std::cout << std::fixed << std::setprecision(0) << std::setw(6) << (*it).first << " Hz " << (*it).second << " dB" << std::endl; + } + + std::cout << "Filtering time " << (end - start) * 1000. / CLOCKS_PER_SEC << " ms" << std::endl; +} diff --git a/src/sound/resid-fp/samp2src.pl b/src/sound/resid-fp/samp2src.pl deleted file mode 100644 index fc6398382e..0000000000 --- a/src/sound/resid-fp/samp2src.pl +++ /dev/null @@ -1,65 +0,0 @@ -#! /usr/bin/perl -w -# --------------------------------------------------------------------------- -# This file is part of reSID, a MOS6581 SID emulator engine. -# Copyright (C) 2004 Dag Lem -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# --------------------------------------------------------------------------- - -use strict; - -die("Usage: samp2src name data-in src-out\n") unless @ARGV == 3; -my ($name, $in, $out) = @ARGV; - -open(F, "<$in") or die($!); -local $/ = undef; -my $data = ; -close(F) or die($!); - -open(F, ">$out") or die($!); - -print F <<\EOF; -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -EOF - -print F "#include \"wave.h\"\n\nreg8 WaveformGeneratorFP::$name\[\] =\n{\n"; - -for (my $i = 0; $i < length($data); $i += 8) { - print F sprintf("/* 0x%03x: */ ", $i), map(sprintf(" 0x%02x,", $_), unpack("C*", substr($data, $i, 8))), "\n"; -} - -print F "};\n"; - -close(F) or die($!); - -exit(0); diff --git a/src/sound/resid-fp/sid.cc b/src/sound/resid-fp/sid.cc deleted file mode 100644 index ad72d9d518..0000000000 --- a/src/sound/resid-fp/sid.cc +++ /dev/null @@ -1,946 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "sid.h" -#include -#include - -extern float convolve(const float *a, const float *b, int n); -extern float convolve_sse(const float *a, const float *b, int n); - -enum host_cpu_feature { - HOST_CPU_MMX=1, HOST_CPU_SSE=2, HOST_CPU_SSE2=4, HOST_CPU_SSE3=8 -}; - -/* This code is appropriate for 32-bit and 64-bit x86 CPUs. */ -#if defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || (defined(_M_X64) && !(defined(_MSC_VER) && !defined(__clang__))) - -struct cpu_x86_regs_s { - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; -}; -typedef struct cpu_x86_regs_s cpu_x86_regs_t; - -static cpu_x86_regs_t get_cpuid_regs(unsigned int index) -{ - cpu_x86_regs_t retval; - -#if defined(_MSC_VER) && !defined(__clang__) /* MSVC assembly */ - __asm { - mov eax, [index] - cpuid - mov [retval.eax], eax - mov [retval.ebx], ebx - mov [retval.ecx], ecx - mov [retval.edx], edx - } -#else /* GNU assembly */ - asm("movl %1, %%eax; cpuid; movl %%eax, %0;" - : "=m" (retval.eax) - : "r" (index) - : "eax", "ebx", "ecx", "edx"); - asm("movl %1, %%eax; cpuid; movl %%ebx, %0;" - : "=m" (retval.ebx) - : "r" (index) - : "eax", "ebx", "ecx", "edx"); - asm("movl %1, %%eax; cpuid; movl %%ecx, %0;" - : "=m" (retval.ecx) - : "r" (index) - : "eax", "ebx", "ecx", "edx"); - asm("movl %1, %%eax; cpuid; movl %%edx, %0;" - : "=m" (retval.edx) - : "r" (index) - : "eax", "ebx", "ecx", "edx"); -#endif - - return retval; -} - -static int host_cpu_features_by_cpuid(void) -{ - cpu_x86_regs_t regs = get_cpuid_regs(1); - - int features = 0; - if (regs.edx & (1 << 23)) - features |= HOST_CPU_MMX; - if (regs.edx & (1 << 25)) - features |= HOST_CPU_SSE; - if (regs.edx & (1 << 26)) - features |= HOST_CPU_SSE2; - if (regs.ecx & (1 << 0)) - features |= HOST_CPU_SSE3; - - return features; -} - -#if (RESID_USE_SSE==1) -static int host_cpu_features(void) -{ - static int features = 0; - static int features_detected = 0; -/* 32-bit only */ -#if defined(__i386__) || (defined(_MSC_VER) && defined(_M_IX86)) - unsigned long temp1, temp2; -#endif - - if (features_detected) - return features; - features_detected = 1; - -#if defined(_MSC_VER) && defined(_M_IX86) /* MSVC compatible assembly appropriate for 32-bit Windows */ - /* see if we are dealing with a cpu that has the cpuid instruction */ - __asm { - pushf - pop eax - mov [temp1], eax - xor eax, 0x200000 - push eax - popf - pushf - pop eax - mov [temp2], eax - push [temp1] - popf - } -#endif -#if defined(__i386__) /* GNU assembly */ - asm("pushfl; popl %%eax; movl %%eax, %0; xorl $0x200000, %%eax; pushl %%eax; popfl; pushfl; popl %%eax; movl %%eax, %1; pushl %0; popfl " - : "=r" (temp1), - "=r" (temp2) - : - : "eax"); -#endif -#if defined(__i386__) || (defined(_MSC_VER) && defined(_M_IX86)) - temp1 &= 0x200000; - temp2 &= 0x200000; - if (temp1 == temp2) { - /* no cpuid support, so we can't test for SSE availability -> false */ - return 0; - } -#endif - - /* find the highest supported cpuid function, returned in %eax */ - if (get_cpuid_regs(0).eax < 1) { - /* no cpuid 1 function, we can't test for features -> no features */ - return 0; - } - - features = host_cpu_features_by_cpuid(); - return features; -} - -#else /* !__x86_64__ && !__i386__ && !_MSC_VER */ -static int host_cpu_features(void) -{ - return 0; -} -#endif -#endif - -float SIDFP::kinked_dac(const int x, const float nonlinearity, const int max) -{ - float value = 0.f; - - int bit = 1; - float weight = 1.f; - const float dir = 2.0f * nonlinearity; - for (int i = 0; i < max; i ++) { - if (x & bit) - value += weight; - bit <<= 1; - weight *= dir; - } - - return value / (weight / nonlinearity) * (1 << max); -} - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -SIDFP::SIDFP() -{ -#if (RESID_USE_SSE==1) - can_use_sse = (host_cpu_features() & HOST_CPU_SSE) != 0; -#else - can_use_sse = false; -#endif - - // Initialize pointers. - sample = 0; - fir = 0; - - voice[0].set_sync_source(&voice[2]); - voice[1].set_sync_source(&voice[0]); - voice[2].set_sync_source(&voice[1]); - - set_sampling_parameters(985248, SAMPLE_INTERPOLATE, 44100); - - bus_value = 0; - bus_value_ttl = 0; - - input(0); -} - - -// ---------------------------------------------------------------------------- -// Destructor. -// ---------------------------------------------------------------------------- -SIDFP::~SIDFP() -{ - delete[] sample; - delete[] fir; -} - - -// ---------------------------------------------------------------------------- -// Set chip model. -// ---------------------------------------------------------------------------- -void SIDFP::set_chip_model(chip_model model) -{ - for (int i = 0; i < 3; i++) { - voice[i].set_chip_model(model); - } - - filter.set_chip_model(model); - extfilt.set_chip_model(model); -} - -/* nonlinear DAC support, set 1 for 8580 / no effect, about 0.96 otherwise */ -void SIDFP::set_voice_nonlinearity(float nl) -{ - for (int i = 0; i < 3; i++) { - voice[i].set_nonlinearity(nl); - } -} - -// ---------------------------------------------------------------------------- -// SID reset. -// ---------------------------------------------------------------------------- -void SIDFP::reset() -{ - for (int i = 0; i < 3; i++) { - voice[i].reset(); - } - filter.reset(); - extfilt.reset(); - - bus_value = 0; - bus_value_ttl = 0; -} - - -// ---------------------------------------------------------------------------- -// Write 16-bit sample to audio input. -// NB! The caller is responsible for keeping the value within 16 bits. -// Note that to mix in an external audio signal, the signal should be -// resampled to 1MHz first to avoid sampling noise. -// ---------------------------------------------------------------------------- -void SIDFP::input(int sample) -{ - // Voice outputs are 20 bits. Scale up to match three voices in order - // to facilitate simulation of the MOS8580 "digi boost" hardware hack. - ext_in = (float) ( (sample << 4) * 3 ); -} - -float SIDFP::output() -{ - const float range = 1 << 15; - return extfilt.output() / (4095.f * 255.f * 3.f * 1.5f / range); -} - -// ---------------------------------------------------------------------------- -// Read registers. -// -// Reading a write only register returns the last byte written to any SID -// register. The individual bits in this value start to fade down towards -// zero after a few cycles. All bits reach zero within approximately -// $2000 - $4000 cycles. -// It has been claimed that this fading happens in an orderly fashion, however -// sampling of write only registers reveals that this is not the case. -// NB! This is not correctly modeled. -// The actual use of write only registers has largely been made in the belief -// that all SID registers are readable. To support this belief the read -// would have to be done immediately after a write to the same register -// (remember that an intermediate write to another register would yield that -// value instead). With this in mind we return the last value written to -// any SID register for $2000 cycles without modeling the bit fading. -// ---------------------------------------------------------------------------- -reg8 SIDFP::read(reg8 offset) -{ - switch (offset) { - case 0x19: - return potx.readPOT(); - case 0x1a: - return poty.readPOT(); - case 0x1b: - return voice[2].wave.readOSC(); - case 0x1c: - return voice[2].envelope.readENV(); - default: - return bus_value; - } -} - - -// ---------------------------------------------------------------------------- -// Write registers. -// ---------------------------------------------------------------------------- -void SIDFP::write(reg8 offset, reg8 value) -{ - bus_value = value; - bus_value_ttl = 0x4000; - - switch (offset) { - case 0x00: - voice[0].wave.writeFREQ_LO(value); - break; - case 0x01: - voice[0].wave.writeFREQ_HI(value); - break; - case 0x02: - voice[0].wave.writePW_LO(value); - break; - case 0x03: - voice[0].wave.writePW_HI(value); - break; - case 0x04: - voice[0].writeCONTROL_REG(value); - break; - case 0x05: - voice[0].envelope.writeATTACK_DECAY(value); - break; - case 0x06: - voice[0].envelope.writeSUSTAIN_RELEASE(value); - break; - case 0x07: - voice[1].wave.writeFREQ_LO(value); - break; - case 0x08: - voice[1].wave.writeFREQ_HI(value); - break; - case 0x09: - voice[1].wave.writePW_LO(value); - break; - case 0x0a: - voice[1].wave.writePW_HI(value); - break; - case 0x0b: - voice[1].writeCONTROL_REG(value); - break; - case 0x0c: - voice[1].envelope.writeATTACK_DECAY(value); - break; - case 0x0d: - voice[1].envelope.writeSUSTAIN_RELEASE(value); - break; - case 0x0e: - voice[2].wave.writeFREQ_LO(value); - break; - case 0x0f: - voice[2].wave.writeFREQ_HI(value); - break; - case 0x10: - voice[2].wave.writePW_LO(value); - break; - case 0x11: - voice[2].wave.writePW_HI(value); - break; - case 0x12: - voice[2].writeCONTROL_REG(value); - break; - case 0x13: - voice[2].envelope.writeATTACK_DECAY(value); - break; - case 0x14: - voice[2].envelope.writeSUSTAIN_RELEASE(value); - break; - case 0x15: - filter.writeFC_LO(value); - break; - case 0x16: - filter.writeFC_HI(value); - break; - case 0x17: - filter.writeRES_FILT(value); - break; - case 0x18: - filter.writeMODE_VOL(value); - break; - default: - break; - } -} - - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -SIDFP::State::State() -{ - int i; - - for (i = 0; i < 0x20; i++) { - sid_register[i] = 0; - } - - bus_value = 0; - bus_value_ttl = 0; - - for (i = 0; i < 3; i++) { - accumulator[i] = 0; - shift_register[i] = 0x7ffff8; - rate_counter[i] = 0; - rate_counter_period[i] = 9; - exponential_counter[i] = 0; - exponential_counter_period[i] = 1; - envelope_counter[i] = 0; - envelope_state[i] = EnvelopeGeneratorFP::RELEASE; - hold_zero[i] = true; - } -} - - -// ---------------------------------------------------------------------------- -// Read state. -// ---------------------------------------------------------------------------- -SIDFP::State SIDFP::read_state() -{ - State state; - int i, j; - - for (i = 0, j = 0; i < 3; i++, j += 7) { - WaveformGeneratorFP& wave = voice[i].wave; - EnvelopeGeneratorFP& envelope = voice[i].envelope; - state.sid_register[j + 0] = wave.freq & 0xff; - state.sid_register[j + 1] = wave.freq >> 8; - state.sid_register[j + 2] = wave.pw & 0xff; - state.sid_register[j + 3] = wave.pw >> 8; - state.sid_register[j + 4] = - (wave.waveform << 4) - | (wave.test ? 0x08 : 0) - | (wave.ring_mod ? 0x04 : 0) - | (wave.sync ? 0x02 : 0) - | (envelope.gate ? 0x01 : 0); - state.sid_register[j + 5] = (envelope.attack << 4) | envelope.decay; - state.sid_register[j + 6] = (envelope.sustain << 4) | envelope.release; - } - - state.sid_register[j++] = filter.fc & 0x007; - state.sid_register[j++] = filter.fc >> 3; - state.sid_register[j++] = (filter.res << 4) | filter.filt; - state.sid_register[j++] = - (filter.voice3off ? 0x80 : 0) - | (filter.hp_bp_lp << 4) - | filter.vol; - - // These registers are superfluous, but included for completeness. - for (; j < 0x1d; j++) { - state.sid_register[j] = read(j); - } - for (; j < 0x20; j++) { - state.sid_register[j] = 0; - } - - state.bus_value = bus_value; - state.bus_value_ttl = bus_value_ttl; - - for (i = 0; i < 3; i++) { - state.accumulator[i] = voice[i].wave.accumulator; - state.shift_register[i] = voice[i].wave.shift_register; - state.rate_counter[i] = voice[i].envelope.rate_counter; - state.rate_counter_period[i] = voice[i].envelope.rate_period; - state.exponential_counter[i] = voice[i].envelope.exponential_counter; - state.exponential_counter_period[i] = voice[i].envelope.exponential_counter_period; - state.envelope_counter[i] = voice[i].envelope.envelope_counter; - state.envelope_state[i] = voice[i].envelope.state; - state.hold_zero[i] = voice[i].envelope.hold_zero; - } - - return state; -} - - -// ---------------------------------------------------------------------------- -// Write state. -// ---------------------------------------------------------------------------- -void SIDFP::write_state(const State& state) -{ - int i; - - for (i = 0; i <= 0x18; i++) { - write(i, state.sid_register[i]); - } - - bus_value = state.bus_value; - bus_value_ttl = state.bus_value_ttl; - - for (i = 0; i < 3; i++) { - voice[i].wave.accumulator = state.accumulator[i]; - voice[i].wave.shift_register = state.shift_register[i]; - voice[i].envelope.rate_counter = state.rate_counter[i]; - voice[i].envelope.rate_period = state.rate_counter_period[i]; - voice[i].envelope.exponential_counter = state.exponential_counter[i]; - voice[i].envelope.exponential_counter_period = state.exponential_counter_period[i]; - voice[i].envelope.envelope_counter = state.envelope_counter[i]; - voice[i].envelope.state = state.envelope_state[i]; - voice[i].envelope.hold_zero = state.hold_zero[i]; - } -} - - -// ---------------------------------------------------------------------------- -// Enable filter. -// ---------------------------------------------------------------------------- -void SIDFP::enable_filter(bool enable) -{ - filter.enable_filter(enable); -} - - -// ---------------------------------------------------------------------------- -// Enable external filter. -// ---------------------------------------------------------------------------- -void SIDFP::enable_external_filter(bool enable) -{ - extfilt.enable_filter(enable); -} - - -// ---------------------------------------------------------------------------- -// I0() computes the 0th order modified Bessel function of the first kind. -// This function is originally from resample-1.5/filterkit.c by J. O. Smith. -// ---------------------------------------------------------------------------- -double SIDFP::I0(double x) -{ - // Max error acceptable in I0 could be 1e-6, which gives that 96 dB already. - // I'm overspecify these errors to get a beautiful FFT dump of the FIR. - const double I0e = 1e-10; - - double sum, u, halfx, temp; - int n; - - sum = u = n = 1; - halfx = x/2.0; - - do { - temp = halfx/n++; - u *= temp*temp; - sum += u; - } while (u >= I0e*sum); - - return sum; -} - - -// ---------------------------------------------------------------------------- -// Setting of SID sampling parameters. -// -// Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64. -// The default end of passband frequency is pass_freq = 0.9*sample_freq/2 -// for sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample -// frequencies. -// -// For resampling, the ratio between the clock frequency and the sample -// frequency is limited as follows: -// 125*clock_freq/sample_freq < 16384 -// E.g. provided a clock frequency of ~ 1MHz, the sample frequency can not -// be set lower than ~ 8kHz. A lower sample frequency would make the -// resampling code overfill its 16k sample ring buffer. -// -// The end of passband frequency is also limited: -// pass_freq <= 0.9*sample_freq/2 - -// E.g. for a 44.1kHz sampling rate the end of passband frequency is limited -// to slightly below 20kHz. This constraint ensures that the FIR table is -// not overfilled. -// ---------------------------------------------------------------------------- -bool SIDFP::set_sampling_parameters(float clock_freq, sampling_method method, - float sample_freq, float pass_freq) -{ - clock_frequency = clock_freq; - sampling = method; - - filter.set_clock_frequency(clock_freq); - extfilt.set_clock_frequency(clock_freq); - adjust_sampling_frequency(sample_freq); - - sample_offset = 0; - sample_prev = 0; - - // FIR initialization is only necessary for resampling. - if (method != SAMPLE_RESAMPLE_INTERPOLATE) - { - delete[] sample; - delete[] fir; - sample = 0; - fir = 0; - return true; - } - - const int bits = 16; - - if (pass_freq > 20000) - pass_freq = 20000; - if (2*pass_freq/sample_freq > 0.9) - pass_freq = 0.9f*sample_freq/2; - - // 16 bits -> -96dB stopband attenuation. - const double A = -20*log10(1.0/(1 << bits)); - - // For calculation of beta and N see the reference for the kaiserord - // function in the MATLAB Signal Processing Toolbox: - // http://www.mathworks.com/access/helpdesk/help/toolbox/signal/kaiserord.html - const double beta = 0.1102*(A - 8.7); - const double I0beta = I0(beta); - - double f_samples_per_cycle = sample_freq/clock_freq; - double f_cycles_per_sample = clock_freq/sample_freq; - - /* This code utilizes the fact that aliasing back to 20 kHz from - * sample_freq/2 is inaudible. This allows us to define a passband - * wider than normally. We might also consider aliasing back to pass_freq, - * but as this can be less than 20 kHz, it might become audible... */ - double aliasing_allowance = sample_freq / 2 - 20000; - if (aliasing_allowance < 0) - aliasing_allowance = 0; - - double transition_bandwidth = sample_freq/2 - pass_freq + aliasing_allowance; - { - /* Filter order according to Kaiser's paper. */ - - int N = (int) ((A - 7.95)/(2 * M_PI * 2.285 * transition_bandwidth/sample_freq) + 0.5); - N += N & 1; - - // The filter length is equal to the filter order + 1. - // The filter length must be an odd number (sinc is symmetric about x = 0). - fir_N = int(N*f_cycles_per_sample) + 1; - fir_N |= 1; - - // Check whether the sample ring buffer would overfill. - if (fir_N > RINGSIZE - 1) - return false; - - /* Error is bound by 1.234 / L^2 */ - fir_RES = (int) (sqrt(1.234 * (1 << bits)) / f_cycles_per_sample + 0.5); - } - - // Allocate memory for FIR tables. - delete[] fir; - fir = new float[fir_N*fir_RES]; - - // The cutoff frequency is midway through the transition band. - double wc = (pass_freq + transition_bandwidth/2) / sample_freq * M_PI * 2; - - // Calculate fir_RES FIR tables for linear interpolation. - for (int i = 0; i < fir_RES; i++) { - double j_offset = double(i)/fir_RES; - // Calculate FIR table. This is the sinc function, weighted by the - // Kaiser window. - for (int j = 0; j < fir_N; j ++) { - double jx = j - fir_N/2. - j_offset; - double wt = wc*jx/f_cycles_per_sample; - double temp = jx/(fir_N/2); - double Kaiser = - fabs(temp) <= 1 ? I0(beta*sqrt(1 - temp*temp))/I0beta : 0; - double sincwt = - fabs(wt) >= 1e-8 ? sin(wt)/wt : 1; - fir[i * fir_N + j] = (float) (f_samples_per_cycle*wc/M_PI*sincwt*Kaiser); - } - } - - // Allocate sample buffer. - if (!sample) { - sample = new float[RINGSIZE*2]; - } - // Clear sample buffer. - for (int j = 0; j < RINGSIZE*2; j++) { - sample[j] = 0; - } - sample_index = 0; - - return true; -} - -// ---------------------------------------------------------------------------- -// Adjustment of SID sampling frequency. -// -// In some applications, e.g. a C64 emulator, it can be desirable to -// synchronize sound with a timer source. This is supported by adjustment of -// the SID sampling frequency. -// -// NB! Adjustment of the sampling frequency may lead to noticeable shifts in -// frequency, and should only be used for interactive applications. Note also -// that any adjustment of the sampling frequency will change the -// characteristics of the resampling filter, since the filter is not rebuilt. -// ---------------------------------------------------------------------------- -void SIDFP::adjust_sampling_frequency(float sample_freq) -{ - cycles_per_sample = clock_frequency/sample_freq; -} - -void SIDFP::age_bus_value(cycle_count n) { - if (bus_value_ttl != 0) { - bus_value_ttl -= n; - if (bus_value_ttl <= 0) { - bus_value = 0; - bus_value_ttl = 0; - } - } -} - -// ---------------------------------------------------------------------------- -// SID clocking - 1 cycle. -// ---------------------------------------------------------------------------- -void SIDFP::clock() -{ - int i; - - // Clock amplitude modulators. - for (i = 0; i < 3; i++) { - voice[i].envelope.clock(); - } - - // Clock oscillators. - for (i = 0; i < 3; i++) { - voice[i].wave.clock(); - } - - // Synchronize oscillators. - for (i = 0; i < 3; i++) { - voice[i].wave.synchronize(); - } - - // Clock filter. - extfilt.clock(filter.clock(voice[0].output(), voice[1].output(), voice[2].output(), ext_in)); -} - -// ---------------------------------------------------------------------------- -// SID clocking with audio sampling. -// Fixpoint arithmetics is used. -// -// The example below shows how to clock the SID a specified amount of cycles -// while producing audio output: -// -// while (delta_t) { -// bufindex += sid.clock(delta_t, buf + bufindex, buflength - bufindex); -// write(dsp, buf, bufindex*2); -// bufindex = 0; -// } -// -// ---------------------------------------------------------------------------- -int SIDFP::clock(cycle_count& delta_t, short* buf, int n, int interleave) -{ - /* XXX I assume n is generally large enough for delta_t here... */ - age_bus_value(delta_t); - int res; - switch (sampling) { - default: - case SAMPLE_INTERPOLATE: - res = clock_interpolate(delta_t, buf, n, interleave); - break; - case SAMPLE_RESAMPLE_INTERPOLATE: - res = clock_resample_interpolate(delta_t, buf, n, interleave); - break; - } - - filter.nuke_denormals(); - extfilt.nuke_denormals(); - - return res; -} - -// ---------------------------------------------------------------------------- -// SID clocking with audio sampling - cycle based with linear sample -// interpolation. -// -// Here the chip is clocked every cycle. This yields higher quality -// sound since the samples are linearly interpolated, and since the -// external filter attenuates frequencies above 16kHz, thus reducing -// sampling noise. -// ---------------------------------------------------------------------------- -RESID_INLINE -int SIDFP::clock_interpolate(cycle_count& delta_t, short* buf, int n, - int interleave) -{ - int s = 0; - int i; - - for (;;) { - float next_sample_offset = sample_offset + cycles_per_sample; - int delta_t_sample = (int) next_sample_offset; - if (delta_t_sample > delta_t) { - break; - } - if (s >= n) { - return s; - } - for (i = 0; i < delta_t_sample - 1; i++) { - clock(); - } - if (i < delta_t_sample) { - sample_prev = output(); - clock(); - } - - delta_t -= delta_t_sample; - sample_offset = next_sample_offset - delta_t_sample; - - float sample_now = output(); - int v = (int)(sample_prev + (sample_offset * (sample_now - sample_prev))); - // Saturated arithmetics to guard against 16 bit sample overflow. - const int half = 1 << 15; - if (v >= half) { - v = half - 1; - } - else if (v < -half) { - v = -half; - } - buf[s++*interleave] = v; - sample_prev = sample_now; - } - - for (i = 0; i < delta_t - 1; i++) { - clock(); - } - if (i < delta_t) { - sample_prev = output(); - clock(); - } - sample_offset -= delta_t; - delta_t = 0; - return s; -} - -// ---------------------------------------------------------------------------- -// SID clocking with audio sampling - cycle based with audio resampling. -// -// This is the theoretically correct (and computationally intensive) audio -// sample generation. The samples are generated by resampling to the specified -// sampling frequency. The work rate is inversely proportional to the -// percentage of the bandwidth allocated to the filter transition band. -// -// This implementation is based on the paper "A Flexible Sampling-Rate -// Conversion Method", by J. O. Smith and P. Gosset, or rather on the -// expanded tutorial on the "Digital Audio Resampling Home Page": -// http://www-ccrma.stanford.edu/~jos/resample/ -// -// By building shifted FIR tables with samples according to the -// sampling frequency, this implementation dramatically reduces the -// computational effort in the filter convolutions, without any loss -// of accuracy. The filter convolutions are also vectorizable on -// current hardware. -// -// Further possible optimizations are: -// * An equiripple filter design could yield a lower filter order, see -// http://www.mwrf.com/Articles/ArticleID/7229/7229.html -// * The Convolution Theorem could be used to bring the complexity of -// convolution down from O(n*n) to O(n*log(n)) using the Fast Fourier -// Transform, see http://en.wikipedia.org/wiki/Convolution_theorem -// * Simply resampling in two steps can also yield computational -// savings, since the transition band will be wider in the first step -// and the required filter order is thus lower in this step. -// Laurent Ganier has found the optimal intermediate sampling frequency -// to be (via derivation of sum of two steps): -// 2 * pass_freq + sqrt [ 2 * pass_freq * orig_sample_freq -// * (dest_sample_freq - 2 * pass_freq) / dest_sample_freq ] -// -// NB! the result of right shifting negative numbers is really -// implementation dependent in the C++ standard. -// ---------------------------------------------------------------------------- -RESID_INLINE -int SIDFP::clock_resample_interpolate(cycle_count& delta_t, short* buf, int n, - int interleave) -{ - int s = 0; - - for (;;) { - float next_sample_offset = sample_offset + cycles_per_sample; - /* full clocks left to next sample */ - int delta_t_sample = (int) next_sample_offset; - if (delta_t_sample > delta_t || s >= n) - break; - - /* clock forward delta_t_sample samples */ - for (int i = 0; i < delta_t_sample; i++) { - clock(); - sample[sample_index] = sample[sample_index + RINGSIZE] = output(); - ++ sample_index; - sample_index &= RINGSIZE - 1; - } - delta_t -= delta_t_sample; - - /* Phase of the sample in terms of clock, [0 .. 1[. */ - sample_offset = next_sample_offset - (float) delta_t_sample; - - /* find the first of the nearest fir tables close to the phase */ - float fir_offset_rmd = sample_offset * fir_RES; - int fir_offset = (int) fir_offset_rmd; - /* [0 .. 1[ */ - fir_offset_rmd -= (float) fir_offset; - - /* find fir_N most recent samples, plus one extra in case the FIR wraps. */ - float* sample_start = sample + sample_index - fir_N + RINGSIZE - 1; - - float v1 = -#if (RESID_USE_SSE==1) - can_use_sse ? convolve_sse(sample_start, fir + fir_offset*fir_N, fir_N) : -#endif - convolve(sample_start, fir + fir_offset*fir_N, fir_N); - - // Use next FIR table, wrap around to first FIR table using - // previous sample. - if (++ fir_offset == fir_RES) { - fir_offset = 0; - ++ sample_start; - } - float v2 = -#if (RESID_USE_SSE==1) - can_use_sse ? convolve_sse(sample_start, fir + fir_offset*fir_N, fir_N) : -#endif - convolve(sample_start, fir + fir_offset*fir_N, fir_N); - - // Linear interpolation between the sinc tables yields good approximation - // for the exact value. - int v = (int) (v1 + fir_offset_rmd * (v2 - v1)); - - // Saturated arithmetics to guard against 16 bit sample overflow. - const int half = 1 << 15; - if (v >= half) { - v = half - 1; - } - else if (v < -half) { - v = -half; - } - - buf[s ++ * interleave] = v; - } - - /* clock forward delta_t samples */ - for (int i = 0; i < delta_t; i++) { - clock(); - sample[sample_index] = sample[sample_index + RINGSIZE] = output(); - ++ sample_index; - sample_index &= RINGSIZE - 1; - } - sample_offset -= (float) delta_t; - delta_t = 0; - return s; -} diff --git a/src/sound/resid-fp/sid.h b/src/sound/resid-fp/sid.h index 5180898fbd..05ad83c3b6 100644 --- a/src/sound/resid-fp/sid.h +++ b/src/sound/resid-fp/sid.h @@ -1,130 +1,372 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#ifndef __SID_FP_H__ -#define __SID_FP_H__ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2011-2016 Leandro Nini + * Copyright 2007-2010 Antti Lankila + * Copyright 2004 Dag Lem + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SIDFP_H +#define SIDFP_H + +#include #include "siddefs-fp.h" -#include "voice.h" -#include "filter.h" -#include "extfilt.h" -#include "pot.h" -class SIDFP +#include "sidcxx11.h" + +namespace reSIDfp { + +class Filter; +class Filter6581; +class Filter8580; +class ExternalFilter; +class Potentiometer; +class Voice; +class Resampler; + +/** + * SID error exception. + */ +class SIDError +{ +private: + const char* message; + public: - SIDFP(); - ~SIDFP(); - - static float kinked_dac(const int x, const float nonlinearity, const int bits); - bool sse_enabled() { return can_use_sse; } - - void set_chip_model(chip_model model); - FilterFP& get_filter() { return filter; } - void enable_filter(bool enable); - void enable_external_filter(bool enable); - bool set_sampling_parameters(float clock_freq, sampling_method method, - float sample_freq, float pass_freq = -1); - void adjust_sampling_frequency(float sample_freq); - void set_voice_nonlinearity(float nonlinearity); - - void clock(); - int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1); - void reset(); - - // Read/write registers. - reg8 read(reg8 offset); - void write(reg8 offset, reg8 value); - - // Read/write state. - class State - { - public: - State(); - - char sid_register[0x20]; - - reg8 bus_value; - cycle_count bus_value_ttl; - - reg24 accumulator[3]; - reg24 shift_register[3]; - reg16 rate_counter[3]; - reg16 rate_counter_period[3]; - reg16 exponential_counter[3]; - reg16 exponential_counter_period[3]; - reg8 envelope_counter[3]; - EnvelopeGeneratorFP::State envelope_state[3]; - bool hold_zero[3]; - }; - - State read_state(); - void write_state(const State& state); - - // 16-bit input (EXT IN). - void input(int sample); - - // output in range -32768 .. 32767, not clipped (AUDIO OUT) - float output(); - -protected: - static double I0(double x); - RESID_INLINE int clock_interpolate(cycle_count& delta_t, short* buf, int n, - int interleave); - RESID_INLINE int clock_resample_interpolate(cycle_count& delta_t, short* buf, - int n, int interleave); - RESID_INLINE void age_bus_value(cycle_count); - - VoiceFP voice[3]; - FilterFP filter; - ExternalFilterFP extfilt; - PotentiometerFP potx; - PotentiometerFP poty; - - reg8 bus_value; - cycle_count bus_value_ttl; - - float clock_frequency; - - // External audio input. - float ext_in; - - enum { RINGSIZE = 16384 }; - - // Sampling variables. - sampling_method sampling; - float cycles_per_sample; - float sample_offset; - int sample_index; - int fir_N; - int fir_RES; - - // Linear interpolation helper - float sample_prev; - - // Ring buffer with overflow for contiguous storage of RINGSIZE samples. - float* sample; - - // FIR_RES filter tables (FIR_N*FIR_RES). - float* fir; - - bool can_use_sse; + SIDError(const char* msg) : + message(msg) {} + const char* getMessage() const { return message; } }; -#endif // not __SID_H__ +/** + * MOS6581/MOS8580 emulation. + */ +class SID +{ +private: + /// Currently active filter + Filter* filter; + + /// Filter used, if model is set to 6581 + std::unique_ptr const filter6581; + + /// Filter used, if model is set to 8580 + std::unique_ptr const filter8580; + + /** + * External filter that provides high-pass and low-pass filtering + * to adjust sound tone slightly. + */ + std::unique_ptr const externalFilter; + + /// Resampler used by audio generation code. + std::unique_ptr resampler; + + /// Paddle X register support + std::unique_ptr const potX; + + /// Paddle Y register support + std::unique_ptr const potY; + + /// SID voices + std::unique_ptr voice[3]; + + /// Time to live for the last written value + int busValueTtl; + + /// Current chip model's bus value TTL + int modelTTL; + + /// Time until #voiceSync must be run. + unsigned int nextVoiceSync; + + /// Currently active chip model. + ChipModel model; + + /// Last written value + unsigned char busValue; + + /// Flags for muted channels + bool muted[3]; + + /** + * Emulated nonlinearity of the envelope DAC. + * + * @See Dac + */ + float envDAC[256]; + + /** + * Emulated nonlinearity of the oscillator DAC. + * + * @See Dac + */ + float oscDAC[4096]; + +private: + /** + * Age the bus value and zero it if it's TTL has expired. + * + * @param n the number of cycles + */ + void ageBusValue(unsigned int n); + + /** + * Get output sample. + * + * @return the output sample + */ + int output() const; + + /** + * Calculate the numebr of cycles according to current parameters + * that it takes to reach sync. + * + * @param sync whether to do the actual voice synchronization + */ + void voiceSync(bool sync); + +public: + SID(); + ~SID(); + + /** + * Set chip model. + * + * @param model chip model to use + * @throw SIDError + */ + void setChipModel(ChipModel model); + + /** + * Get currently emulated chip model. + */ + ChipModel getChipModel() const { return model; } + + /** + * SID reset. + */ + void reset(); + + /** + * 16-bit input (EXT IN). Write 16-bit sample to audio input. NB! The caller + * is responsible for keeping the value within 16 bits. Note that to mix in + * an external audio signal, the signal should be resampled to 1MHz first to + * avoid sampling noise. + * + * @param value input level to set + */ + void input(int value); + + /** + * Read registers. + * + * Reading a write only register returns the last char written to any SID register. + * The individual bits in this value start to fade down towards zero after a few cycles. + * All bits reach zero within approximately $2000 - $4000 cycles. + * It has been claimed that this fading happens in an orderly fashion, + * however sampling of write only registers reveals that this is not the case. + * NOTE: This is not correctly modeled. + * The actual use of write only registers has largely been made + * in the belief that all SID registers are readable. + * To support this belief the read would have to be done immediately + * after a write to the same register (remember that an intermediate write + * to another register would yield that value instead). + * With this in mind we return the last value written to any SID register + * for $2000 cycles without modeling the bit fading. + * + * @param offset SID register to read + * @return value read from chip + */ + unsigned char read(int offset); + + /** + * Write registers. + * + * @param offset chip register to write + * @param value value to write + */ + void write(int offset, unsigned char value); + + /** + * SID voice muting. + * + * @param channel channel to modify + * @param enable is muted? + */ + void mute(int channel, bool enable) { muted[channel] = enable; } + + /** + * Setting of SID sampling parameters. + * + * Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64. + * The default end of passband frequency is pass_freq = 0.9*sample_freq/2 + * for sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample frequencies. + * + * For resampling, the ratio between the clock frequency and the sample frequency + * is limited as follows: 125*clock_freq/sample_freq < 16384 + * E.g. provided a clock frequency of ~ 1MHz, the sample frequency can not be set + * lower than ~ 8kHz. A lower sample frequency would make the resampling code + * overfill its 16k sample ring buffer. + * + * The end of passband frequency is also limited: pass_freq <= 0.9*sample_freq/2 + * + * E.g. for a 44.1kHz sampling rate the end of passband frequency + * is limited to slightly below 20kHz. + * This constraint ensures that the FIR table is not overfilled. + * + * @param clockFrequency System clock frequency at Hz + * @param method sampling method to use + * @param samplingFrequency Desired output sampling rate + * @param highestAccurateFrequency + * @throw SIDError + */ + void setSamplingParameters(double clockFrequency, SamplingMethod method, double samplingFrequency, double highestAccurateFrequency); + + /** + * Clock SID forward using chosen output sampling algorithm. + * + * @param cycles c64 clocks to clock + * @param buf audio output buffer + * @return number of samples produced + */ + int clock(unsigned int cycles, short* buf); + + /** + * Clock SID forward with no audio production. + * + * _Warning_: + * You can't mix this method of clocking with the audio-producing + * clock() because components that don't affect OSC3/ENV3 are not + * emulated. + * + * @param cycles c64 clocks to clock. + */ + void clockSilent(unsigned int cycles); + + /** + * Set filter curve parameter for 6581 model. + * + * @see Filter6581::setFilterCurve(double) + */ + void setFilter6581Curve(double filterCurve); + + /** + * Set filter curve parameter for 8580 model. + * + * @see Filter8580::setFilterCurve(double) + */ + void setFilter8580Curve(double filterCurve); + + /** + * Enable filter emulation. + * + * @param enable false to turn off filter emulation + */ + void enableFilter(bool enable); +}; + +} // namespace reSIDfp + +#if RESID_INLINING || defined(SID_CPP) + +#include + +#include "Filter.h" +#include "ExternalFilter.h" +#include "Voice.h" +#include "resample/Resampler.h" + +namespace reSIDfp +{ + +RESID_INLINE +void SID::ageBusValue(unsigned int n) +{ + if (likely(busValueTtl != 0)) + { + busValueTtl -= n; + + if (unlikely(busValueTtl <= 0)) + { + busValue = 0; + busValueTtl = 0; + } + } +} + +RESID_INLINE +int SID::output() const +{ + const int v1 = voice[0]->output(voice[2]->wave()); + const int v2 = voice[1]->output(voice[0]->wave()); + const int v3 = voice[2]->output(voice[1]->wave()); + + return externalFilter->clock(filter->clock(v1, v2, v3)); +} + + +RESID_INLINE +int SID::clock(unsigned int cycles, short* buf) +{ + ageBusValue(cycles); + int s = 0; + + while (cycles != 0) + { + unsigned int delta_t = std::min(nextVoiceSync, cycles); + + if (likely(delta_t > 0)) + { + for (unsigned int i = 0; i < delta_t; i++) + { + // clock waveform generators + voice[0]->wave()->clock(); + voice[1]->wave()->clock(); + voice[2]->wave()->clock(); + + // clock envelope generators + voice[0]->envelope()->clock(); + voice[1]->envelope()->clock(); + voice[2]->envelope()->clock(); + + if (unlikely(resampler->input(output()))) + { + buf[s++] = resampler->getOutput(); + } + } + + cycles -= delta_t; + nextVoiceSync -= delta_t; + } + + if (unlikely(nextVoiceSync == 0)) + { + voiceSync(true); + } + } + + return s; +} + +} // namespace reSIDfp + +#endif + +#endif diff --git a/src/sound/resid-fp/sidcxx11.h b/src/sound/resid-fp/sidcxx11.h new file mode 100644 index 0000000000..96380be777 --- /dev/null +++ b/src/sound/resid-fp/sidcxx11.h @@ -0,0 +1,58 @@ +/* + * This file is part of libsidplayfp, a SID player engine. + * + * Copyright 2014-2022 Leandro Nini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SIDCXX_H +#define SIDCXX_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define HAVE_CXX11 true + + +#ifdef HAVE_CXX17 +# define HAVE_CXX14 +# define MAYBE_UNUSED [[ maybe_unused ]] +#else +# define MAYBE_UNUSED +#endif + +#ifdef HAVE_CXX14 +# define HAVE_CXX11 +# define MAKE_UNIQUE(type, ...) std::make_unique(__VA_ARGS__) +#else +# define MAKE_UNIQUE(type, ...) std::unique_ptr(new type(__VA_ARGS__)) +#endif + +#ifndef HAVE_CXX11 +# define nullptr 0 +# define override +# define final +# define unique_ptr auto_ptr +# define DEFAULT {} +# define DELETE {} +#else +# define DEFAULT = default +# define DELETE = delete +#endif + + +#endif diff --git a/src/sound/resid-fp/siddefs-fp.h b/src/sound/resid-fp/siddefs-fp.h index fb10d5dff2..7061e3a85d 100644 --- a/src/sound/resid-fp/siddefs-fp.h +++ b/src/sound/resid-fp/siddefs-fp.h @@ -14,75 +14,49 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // --------------------------------------------------------------------------- -#ifndef __SIDDEFS_FP_H__ -#define __SIDDEFS_FP_H__ +#ifndef SIDDEFS_FP_H +#define SIDDEFS_FP_H + +// Compilation configuration. +#define RESID_BRANCH_HINTS true + +// Compiler specifics. +#define HAVE_BUILTIN_EXPECT true #ifndef M_PI -#define M_PI 3.14159265358979323846 -#define M_PI_f 3.14159265358979323846f -#else -#define M_PI_f ((float) M_PI) +# define M_PI 3.14159265358979323846 #endif -#ifndef M_LN2 -#define M_LN2 0.69314718055994530942 -#define M_LN2_f 0.69314718055994530942f +// Branch prediction macros, lifted off the Linux kernel. +#if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) #else -#define M_LN2_f ((float) M_LN2) +# define likely(x) (x) +# define unlikely(x) (x) #endif -// Define bool, true, and false for C++ compilers that lack these keywords. -#define RESID_HAVE_BOOL 1 - -#if !RESID_HAVE_BOOL -typedef int bool; -const bool true = 1; -const bool false = 0; -#endif - -// We could have used the smallest possible data type for each SID register, -// however this would give a slower engine because of data type conversions. -// An int is assumed to be at least 32 bits (necessary in the types reg24, -// cycle_count, and sound_sample). GNU does not support 16-bit machines -// (GNU Coding Standards: Portability between CPUs), so this should be -// a valid assumption. - -typedef unsigned int reg4; -typedef unsigned int reg8; -typedef unsigned int reg12; -typedef unsigned int reg16; -typedef unsigned int reg24; +namespace reSIDfp { -typedef int cycle_count; +typedef enum { MOS6581=1, MOS8580 } ChipModel; -enum chip_model { MOS6581FP=1, MOS8580FP }; - -enum sampling_method { SAMPLE_INTERPOLATE=1, SAMPLE_RESAMPLE_INTERPOLATE }; +typedef enum { DECIMATE=1, RESAMPLE } SamplingMethod; +} extern "C" { #ifndef __VERSION_CC__ -extern const char* resid_version_string; +extern const char* residfp_version_string; #else -const char* resid_version_string = VERSION; +const char* residfp_version_string = VERSION; #endif } // Inlining on/off. +#define RESID_INLINING true #define RESID_INLINE inline -#if defined(__SSE__) || (defined(_M_IX86_FP ) && _M_IX86_FP >= 1) || defined(_M_X64) -#define RESID_USE_SSE 1 -#else -#define RESID_USE_SSE 0 -#endif - -#define HAVE_LOGF -#define HAVE_EXPF -#define HAVE_LOGF_PROTOTYPE -#define HAVE_EXPF_PROTOTYPE - -#endif // not __SIDDEFS_H__ +#endif // SIDDEFS_FP_H diff --git a/src/sound/resid-fp/siddefs-fp.h.in b/src/sound/resid-fp/siddefs-fp.h.in index ec44b36191..4c31ffb461 100644 --- a/src/sound/resid-fp/siddefs-fp.h.in +++ b/src/sound/resid-fp/siddefs-fp.h.in @@ -14,74 +14,49 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // --------------------------------------------------------------------------- -#ifndef __SIDDEFS_FP_H__ -#define __SIDDEFS_FP_H__ +#ifndef SIDDEFS_FP_H +#define SIDDEFS_FP_H + +// Compilation configuration. +#define RESID_BRANCH_HINTS @RESID_BRANCH_HINTS@ + +// Compiler specifics. +#define HAVE_BUILTIN_EXPECT @HAVE_BUILTIN_EXPECT@ #ifndef M_PI -#define M_PI 3.14159265358979323846 -#define M_PI_f 3.14159265358979323846f -#else -#define M_PI_f ((float) M_PI) +# define M_PI 3.14159265358979323846 #endif -#ifndef M_LN2 -#define M_LN2 0.69314718055994530942 -#define M_LN2_f 0.69314718055994530942f +// Branch prediction macros, lifted off the Linux kernel. +#if RESID_BRANCH_HINTS && HAVE_BUILTIN_EXPECT +# define likely(x) __builtin_expect(!!(x), 1) +# define unlikely(x) __builtin_expect(!!(x), 0) #else -#define M_LN2_f ((float) M_LN2) +# define likely(x) (x) +# define unlikely(x) (x) #endif -// Define bool, true, and false for C++ compilers that lack these keywords. -#define RESID_HAVE_BOOL @RESID_HAVE_BOOL@ - -#if !RESID_HAVE_BOOL -typedef int bool; -const bool true = 1; -const bool false = 0; -#endif - -// We could have used the smallest possible data type for each SID register, -// however this would give a slower engine because of data type conversions. -// An int is assumed to be at least 32 bits (necessary in the types reg24, -// cycle_count, and sound_sample). GNU does not support 16-bit machines -// (GNU Coding Standards: Portability between CPUs), so this should be -// a valid assumption. - -typedef unsigned int reg4; -typedef unsigned int reg8; -typedef unsigned int reg12; -typedef unsigned int reg16; -typedef unsigned int reg24; +namespace reSIDfp { -typedef int cycle_count; +typedef enum { MOS6581=1, MOS8580 } ChipModel; -enum chip_model { MOS6581FP=1, MOS8580FP }; - -enum sampling_method { SAMPLE_INTERPOLATE=1, SAMPLE_RESAMPLE_INTERPOLATE }; +typedef enum { DECIMATE=1, RESAMPLE } SamplingMethod; +} extern "C" { #ifndef __VERSION_CC__ -extern const char* resid_version_string; +extern const char* residfp_version_string; #else -const char* resid_version_string = VERSION; +const char* residfp_version_string = "@PACKAGE_VERSION@"; #endif } // Inlining on/off. +#define RESID_INLINING @RESID_INLINING@ #define RESID_INLINE @RESID_INLINE@ -#define RESID_USE_SSE @RESID_USE_SSE@ - -#if @HAVE_LOGF_PROTOTYPE@ -#define HAVE_LOGF_PROTOTYPE -#endif - -#if @HAVE_EXPF_PROTOTYPE@ -#define HAVE_EXPF_PROTOTYPE -#endif - -#endif // not __SIDDEFS_H__ +#endif // SIDDEFS_FP_H diff --git a/src/sound/resid-fp/version.cc b/src/sound/resid-fp/version.cc index fe9d4595fa..3ed8b44909 100644 --- a/src/sound/resid-fp/version.cc +++ b/src/sound/resid-fp/version.cc @@ -14,7 +14,7 @@ // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // --------------------------------------------------------------------------- #define __VERSION_CC__ diff --git a/src/sound/resid-fp/voice.cc b/src/sound/resid-fp/voice.cc deleted file mode 100644 index 18c36cc71c..0000000000 --- a/src/sound/resid-fp/voice.cc +++ /dev/null @@ -1,102 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#define __VOICE_CC__ -#include "voice.h" -#include "sid.h" - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -VoiceFP::VoiceFP() -{ - nonlinearity = 1.f; - set_chip_model(MOS6581FP); -} - -/* Keep this at 1.f for 8580, there are no 6581-only codepaths in this file! */ -void VoiceFP::set_nonlinearity(float nl) -{ - nonlinearity = nl; - calculate_dac_tables(); -} - -// ---------------------------------------------------------------------------- -// Set chip model. -// ---------------------------------------------------------------------------- -void VoiceFP::set_chip_model(chip_model model) -{ - wave.set_chip_model(model); - - if (model == MOS6581FP) { - /* there is some level from each voice even if the env is down and osc - * is stopped. You can hear this by routing a voice into filter (filter - * should be kept disabled for this) as the master level changes. This - * tunable affects the volume of digis. */ - voice_DC = 0x800 * 0xff; - /* In 8580 the waveforms seem well centered, but on the 6581 there is some - * offset change as envelope grows, indicating that the waveforms are not - * perfectly centered. I estimate the value ~ 0x600 for my R4AR, and ReSID - * has used another measurement technique and got 0x380. */ - wave_zero = 0x600; - calculate_dac_tables(); - } - else { - /* 8580 is thought to be perfect, apart from small negative offset due to - * ext-in mixing, I think. */ - voice_DC = 0; - wave_zero = 0x800; - calculate_dac_tables(); - } -} - -void VoiceFP::calculate_dac_tables() -{ - int i; - for (i = 0; i < 256; i ++) - env_dac[i] = SIDFP::kinked_dac(i, nonlinearity, 8); - for (i = 0; i < 4096; i ++) - voice_dac[i] = SIDFP::kinked_dac(i, nonlinearity, 12) - wave_zero; -} - -// ---------------------------------------------------------------------------- -// Set sync source. -// ---------------------------------------------------------------------------- -void VoiceFP::set_sync_source(VoiceFP* source) -{ - wave.set_sync_source(&source->wave); -} - -// ---------------------------------------------------------------------------- -// Register functions. -// ---------------------------------------------------------------------------- -void VoiceFP::writeCONTROL_REG(reg8 control) -{ - wave.writeCONTROL_REG(control); - envelope.writeCONTROL_REG(control); -} - -// ---------------------------------------------------------------------------- -// SID reset. -// ---------------------------------------------------------------------------- -void VoiceFP::reset() -{ - wave.reset(); - envelope.reset(); -} diff --git a/src/sound/resid-fp/voice.h b/src/sound/resid-fp/voice.h deleted file mode 100644 index 3a9e3fc95c..0000000000 --- a/src/sound/resid-fp/voice.h +++ /dev/null @@ -1,73 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#ifndef __VOICE_H__ -#define __VOICE_H__ - -#include "siddefs-fp.h" -#include "wave.h" -#include "envelope.h" - -class VoiceFP -{ -public: - VoiceFP(); - - void set_chip_model(chip_model model); - void set_sync_source(VoiceFP*); - void reset(); - - void writeCONTROL_REG(reg8); - - // Amplitude modulated waveform output. - // Range [-2048*255, 2047*255]. - RESID_INLINE float output(); - - void set_nonlinearity(float nl); -protected: - void calculate_dac_tables(); - - WaveformGeneratorFP wave; - EnvelopeGeneratorFP envelope; - - // Multiplying D/A DC offset. - float voice_DC, wave_zero, nonlinearity; - - float env_dac[256]; - float voice_dac[4096]; -friend class SIDFP; -}; - -// ---------------------------------------------------------------------------- -// Amplitude modulated waveform output. -// Ideal range [-2048*255, 2047*255]. -// ---------------------------------------------------------------------------- - -RESID_INLINE -float VoiceFP::output() -{ - unsigned int w = wave.output(); - unsigned int e = envelope.output(); - float _w = voice_dac[w]; - float _e = env_dac[e]; - - return _w * _e + voice_DC; -} - -#endif // not __VOICE_H__ diff --git a/src/sound/resid-fp/wave.cc b/src/sound/resid-fp/wave.cc deleted file mode 100644 index 018c4e2be6..0000000000 --- a/src/sound/resid-fp/wave.cc +++ /dev/null @@ -1,151 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#define __WAVE_CC__ -#include "wave.h" - -// ---------------------------------------------------------------------------- -// Constructor. -// ---------------------------------------------------------------------------- -WaveformGeneratorFP::WaveformGeneratorFP() -{ - sync_source = this; - - set_chip_model(MOS6581FP); - - reset(); -} - - -// ---------------------------------------------------------------------------- -// Set sync source. -// ---------------------------------------------------------------------------- -void WaveformGeneratorFP::set_sync_source(WaveformGeneratorFP* source) -{ - sync_source = source; - source->sync_dest = this; -} - - -// ---------------------------------------------------------------------------- -// Set chip model. -// ---------------------------------------------------------------------------- -void WaveformGeneratorFP::set_chip_model(chip_model model) -{ - if (model == MOS6581FP) { - wave__ST = wave6581__ST; - wave_P_T = wave6581_P_T; - wave_PS_ = wave6581_PS_; - wave_PST = wave6581_PST; - } - else { - wave__ST = wave8580__ST; - wave_P_T = wave8580_P_T; - wave_PS_ = wave8580_PS_; - wave_PST = wave8580_PST; - } -} - - -// ---------------------------------------------------------------------------- -// Register functions. -// ---------------------------------------------------------------------------- -void WaveformGeneratorFP::writeFREQ_LO(reg8 freq_lo) -{ - freq = (freq & 0xff00) | (freq_lo & 0x00ff); -} - -void WaveformGeneratorFP::writeFREQ_HI(reg8 freq_hi) -{ - freq = ((freq_hi << 8) & 0xff00) | (freq & 0x00ff); -} - -/* The original form was (acc >> 12) >= pw, where truth value is not affected - * by the contents of the low 12 bits. Therefore the lowest bits must be zero - * in the new formulation acc >= (pw << 12). */ -void WaveformGeneratorFP::writePW_LO(reg8 pw_lo) -{ - pw = (pw & 0xf00) | (pw_lo & 0x0ff); - pw_acc_scale = pw << 12; -} - -void WaveformGeneratorFP::writePW_HI(reg8 pw_hi) -{ - pw = ((pw_hi << 8) & 0xf00) | (pw & 0x0ff); - pw_acc_scale = pw << 12; -} - -void WaveformGeneratorFP::writeCONTROL_REG(reg8 control) -{ - waveform = (control >> 4) & 0x0f; - ring_mod = control & 0x04; - sync = control & 0x02; - - reg8 test_next = control & 0x08; - - /* SounDemoN found out that test bit can be used to control the noise - * register. Hear the result in Bojojoing.sid. */ - - // testbit set. invert bit 19 and write it to bit 1 - if (test_next && !test) { - accumulator = 0; - reg24 bit19 = (shift_register >> 19) & 1; - shift_register = (shift_register & 0x7ffffd) | ((bit19^1) << 1); - noise_overwrite_delay = 200000; /* 200 ms, probably too generous? */ - } - // Test bit cleared. - // The accumulator starts counting, and the shift register is reset to - // the value 0x7ffff8. - else if (!test_next && test) { - reg24 bit0 = ((shift_register >> 22) ^ (shift_register >> 17)) & 0x1; - shift_register <<= 1; - shift_register |= bit0; - } - // clear output bits of shift register if noise and other waveforms - // are selected simultaneously - if (waveform > 8) { - shift_register &= 0x7fffff^(1<<22)^(1<<20)^(1<<16)^(1<<13)^(1<<11)^(1<<7)^(1<<4)^(1<<2); - } - - test = test_next; - - /* update noise anyway, just in case the above paths triggered */ - noise_output_cached = outputN___(); -} - -reg8 WaveformGeneratorFP::readOSC() -{ - return output() >> 4; -} - -// ---------------------------------------------------------------------------- -// SID reset. -// ---------------------------------------------------------------------------- -void WaveformGeneratorFP::reset() -{ - accumulator = 0; - previous = 0; - shift_register = 0x7ffffc; - freq = 0; - pw = 0; - pw_acc_scale = 0; - test = 0; - writeCONTROL_REG(0); - msb_rising = false; -} diff --git a/src/sound/resid-fp/wave.h b/src/sound/resid-fp/wave.h deleted file mode 100644 index 64684228b9..0000000000 --- a/src/sound/resid-fp/wave.h +++ /dev/null @@ -1,457 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#ifndef __WAVE_H__ -#define __WAVE_H__ - -#include "siddefs-fp.h" - -// ---------------------------------------------------------------------------- -// A 24 bit accumulator is the basis for waveform generation. FREQ is added to -// the lower 16 bits of the accumulator each cycle. -// The accumulator is set to zero when TEST is set, and starts counting -// when TEST is cleared. -// The noise waveform is taken from intermediate bits of a 23 bit shift -// register. This register is clocked by bit 19 of the accumulator. -// ---------------------------------------------------------------------------- -class WaveformGeneratorFP -{ -public: - WaveformGeneratorFP(); - - void set_sync_source(WaveformGeneratorFP*); - void set_chip_model(chip_model model); - - RESID_INLINE void clock(); - RESID_INLINE void synchronize(); - void reset(); - - void writeFREQ_LO(reg8); - void writeFREQ_HI(reg8); - void writePW_LO(reg8); - void writePW_HI(reg8); - void writeCONTROL_REG(reg8); - reg8 readOSC(); - - // 12-bit waveform output. - RESID_INLINE reg12 output(); - -protected: - const WaveformGeneratorFP* sync_source; - WaveformGeneratorFP* sync_dest; - - // Tell whether the accumulator MSB was set high on this cycle. - bool msb_rising; - - reg24 accumulator; - reg24 shift_register; - reg12 previous, noise_output_cached; - int noise_overwrite_delay; - - // Fout = (Fn*Fclk/16777216)Hz - reg16 freq; - // PWout = (PWn/40.95)%, also the same << 12 for direct comparison against acc - reg12 pw; reg24 pw_acc_scale; - - // The control register right-shifted 4 bits; used for output function - // table lookup. - reg8 waveform; - - // The remaining control register bits. - reg8 test; - reg8 ring_mod; - reg8 sync; - // The gate bit is handled by the EnvelopeGenerator. - - // 16 possible combinations of waveforms. - RESID_INLINE reg12 output___T(); - RESID_INLINE reg12 output__S_(); - RESID_INLINE reg12 output__ST(); - RESID_INLINE reg12 output_P__(); - RESID_INLINE reg12 output_P_T(); - RESID_INLINE reg12 output_PS_(); - RESID_INLINE reg12 output_PST(); - RESID_INLINE reg12 outputN___(); - RESID_INLINE reg12 outputN__T(); - RESID_INLINE reg12 outputN_S_(); - RESID_INLINE reg12 outputN_ST(); - RESID_INLINE reg12 outputNP__(); - RESID_INLINE reg12 outputNP_T(); - RESID_INLINE reg12 outputNPS_(); - RESID_INLINE reg12 outputNPST(); - - // Sample data for combinations of waveforms. - static reg8 wave6581__ST[]; - static reg8 wave6581_P_T[]; - static reg8 wave6581_PS_[]; - static reg8 wave6581_PST[]; - - static reg8 wave8580__ST[]; - static reg8 wave8580_P_T[]; - static reg8 wave8580_PS_[]; - static reg8 wave8580_PST[]; - - reg8* wave__ST; - reg8* wave_P_T; - reg8* wave_PS_; - reg8* wave_PST; - -friend class VoiceFP; -friend class SIDFP; -}; - -// ---------------------------------------------------------------------------- -// SID clocking - 1 cycle. -// ---------------------------------------------------------------------------- -RESID_INLINE -void WaveformGeneratorFP::clock() -{ - /* no digital operation if test bit is set. Only emulate analog fade. */ - if (test) { - if (noise_overwrite_delay != 0) { - if (-- noise_overwrite_delay == 0) { - shift_register |= 0x7ffffc; - noise_output_cached = outputN___(); - } - } - return; - } - - reg24 accumulator_prev = accumulator; - - // Calculate new accumulator value; - accumulator += freq; - accumulator &= 0xffffff; - - // Check whether the MSB became set high. This is used for synchronization. - msb_rising = !(accumulator_prev & 0x800000) && (accumulator & 0x800000); - - // Shift noise register once for each time accumulator bit 19 is set high. - if (!(accumulator_prev & 0x080000) && (accumulator & 0x080000)) { - reg24 bit0 = ((shift_register >> 22) ^ (shift_register >> 17)) & 0x1; - shift_register <<= 1; - // optimization: fall into the bit bucket - //shift_register &= 0x7fffff; - shift_register |= bit0; - - /* since noise changes relatively infrequently, we'll avoid the relatively - * expensive bit shuffling at output time. */ - noise_output_cached = outputN___(); - } - - // clear output bits of shift register if noise and other waveforms - // are selected simultaneously - if (waveform > 8) { - shift_register &= 0x7fffff^(1<<22)^(1<<20)^(1<<16)^(1<<13)^(1<<11)^(1<<7)^(1<<4)^(1<<2); - noise_output_cached = outputN___(); - } -} - -// ---------------------------------------------------------------------------- -// Synchronize oscillators. -// This must be done after all the oscillators have been clock()'ed since the -// oscillators operate in parallel. -// Note that the oscillators must be clocked exactly on the cycle when the -// MSB is set high for hard sync to operate correctly. See SID::clock(). -// ---------------------------------------------------------------------------- -RESID_INLINE -void WaveformGeneratorFP::synchronize() -{ - // A special case occurs when a sync source is synced itself on the same - // cycle as when its MSB is set high. In this case the destination will - // not be synced. This has been verified by sampling OSC3. - if (msb_rising && sync_dest->sync && !(sync && sync_source->msb_rising)) { - sync_dest->accumulator = 0; - } -} - - -// ---------------------------------------------------------------------------- -// Output functions. -// NB! The output from SID 8580 is delayed one cycle compared to SID 6581, -// this is not modeled. -// ---------------------------------------------------------------------------- - -// Triangle: -// The upper 12 bits of the accumulator are used. -// The MSB is used to create the falling edge of the triangle by inverting -// the lower 11 bits. The MSB is thrown away and the lower 11 bits are -// left-shifted (half the resolution, full amplitude). -// Ring modulation substitutes the MSB with MSB EOR sync_source MSB. -// -RESID_INLINE -reg12 WaveformGeneratorFP::output___T() -{ - reg24 msb = (ring_mod ? accumulator ^ sync_source->accumulator : accumulator) - & 0x800000; - return ((msb ? ~accumulator : accumulator) >> 11) & 0xfff; -} - -// Sawtooth: -// The output is identical to the upper 12 bits of the accumulator. -// -RESID_INLINE -reg12 WaveformGeneratorFP::output__S_() -{ - return accumulator >> 12; -} - -// Pulse: -// The upper 12 bits of the accumulator are used. -// These bits are compared to the pulse width register by a 12 bit digital -// comparator; output is either all one or all zero bits. -// NB! The output is actually delayed one cycle after the compare. -// This is not modeled. -// -// The test bit, when set to one, holds the pulse waveform output at 0xfff -// regardless of the pulse width setting. -// -RESID_INLINE -reg12 WaveformGeneratorFP::output_P__() -{ - return (test || accumulator >= pw_acc_scale) ? 0xfff : 0x000; -} - -// Noise: -// The noise output is taken from intermediate bits of a 23-bit shift register -// which is clocked by bit 19 of the accumulator. -// NB! The output is actually delayed 2 cycles after bit 19 is set high. -// This is not modeled. -// -// Operation: Calculate EOR result, shift register, set bit 0 = result. -// -// ----------------------->--------------------- -// | | -// ----EOR---- | -// | | | -// 2 2 2 1 1 1 1 1 1 1 1 1 1 | -// Register bits: 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 <--- -// | | | | | | | | -// OSC3 bits : 7 6 5 4 3 2 1 0 -// -// Since waveform output is 12 bits the output is left-shifted 4 times. -// -RESID_INLINE -reg12 WaveformGeneratorFP::outputN___() -{ - return - ((shift_register & 0x400000) >> 11) | - ((shift_register & 0x100000) >> 10) | - ((shift_register & 0x010000) >> 7) | - ((shift_register & 0x002000) >> 5) | - ((shift_register & 0x000800) >> 4) | - ((shift_register & 0x000080) >> 1) | - ((shift_register & 0x000010) << 1) | - ((shift_register & 0x000004) << 2); -} - -// Combined waveforms: -// By combining waveforms, the bits of each waveform are effectively short -// circuited. A zero bit in one waveform will result in a zero output bit -// (thus the infamous claim that the waveforms are AND'ed). -// However, a zero bit in one waveform will also affect the neighboring bits -// in the output. The reason for this has not been determined. -// -// Example: -// -// 1 1 -// Bit # 1 0 9 8 7 6 5 4 3 2 1 0 -// ----------------------- -// Sawtooth 0 0 0 1 1 1 1 1 1 0 0 0 -// -// Triangle 0 0 1 1 1 1 1 1 0 0 0 0 -// -// AND 0 0 0 1 1 1 1 1 0 0 0 0 -// -// Output 0 0 0 0 1 1 1 0 0 0 0 0 -// -// -// This behavior would be quite difficult to model exactly, since the SID -// in this case does not act as a digital state machine. Tests show that minor -// (1 bit) differences can actually occur in the output from otherwise -// identical samples from OSC3 when waveforms are combined. To further -// complicate the situation the output changes slightly with time (more -// neighboring bits are successively set) when the 12-bit waveform -// registers are kept unchanged. -// -// It is probably possible to come up with a valid model for the -// behavior, however this would be far too slow for practical use since it -// would have to be based on the mutual influence of individual bits. -// -// The output is instead approximated by using the upper bits of the -// accumulator as an index to look up the combined output in a table -// containing actual combined waveform samples from OSC3. -// These samples are 8 bit, so 4 bits of waveform resolution is lost. -// All OSC3 samples are taken with FREQ=0x1000, adding a 1 to the upper 12 -// bits of the accumulator each cycle for a sample period of 4096 cycles. -// -// Sawtooth+Triangle: -// The sawtooth output is used to look up an OSC3 sample. -// -// Pulse+Triangle: -// The triangle output is right-shifted and used to look up an OSC3 sample. -// The sample is output if the pulse output is on. -// The reason for using the triangle output as the index is to handle ring -// modulation. Only the first half of the sample is used, which should be OK -// since the triangle waveform has half the resolution of the accumulator. -// -// Pulse+Sawtooth: -// The sawtooth output is used to look up an OSC3 sample. -// The sample is output if the pulse output is on. -// -// Pulse+Sawtooth+Triangle: -// The sawtooth output is used to look up an OSC3 sample. -// The sample is output if the pulse output is on. -// -RESID_INLINE -reg12 WaveformGeneratorFP::output__ST() -{ - return wave__ST[output__S_()] << 4; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::output_P_T() -{ - /* ring modulation does something odd with this waveform. But I don't know - * how to emulate it. */ - return (wave_P_T[output___T() >> 1] << 4) & output_P__(); -} - -RESID_INLINE -reg12 WaveformGeneratorFP::output_PS_() -{ - return (wave_PS_[output__S_()] << 4) & output_P__(); -} - -RESID_INLINE -reg12 WaveformGeneratorFP::output_PST() -{ - return (wave_PST[output__S_()] << 4) & output_P__(); -} - -// Combined waveforms including noise: -// All waveform combinations including noise output zero after a few cycles. -// NB! The effects of such combinations are not fully explored. It is claimed -// that the shift register may be filled with zeroes and locked up, which -// seems to be true. -// We have not attempted to model this behavior, suffice to say that -// there is very little audible output from waveform combinations including -// noise. We hope that nobody is actually using it. -// -RESID_INLINE -reg12 WaveformGeneratorFP::outputN__T() -{ - return 0; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::outputN_S_() -{ - return 0; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::outputN_ST() -{ - return 0; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::outputNP__() -{ - return 0; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::outputNP_T() -{ - return 0; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::outputNPS_() -{ - return 0; -} - -RESID_INLINE -reg12 WaveformGeneratorFP::outputNPST() -{ - return 0; -} - -// ---------------------------------------------------------------------------- -// Select one of 16 possible combinations of waveforms. -// ---------------------------------------------------------------------------- -RESID_INLINE -reg12 WaveformGeneratorFP::output() -{ - switch (waveform) { - case 0x1: - previous = output___T(); - break; - case 0x2: - previous = output__S_(); - break; - case 0x3: - previous = output__ST(); - break; - case 0x4: - previous = output_P__(); - break; - case 0x5: - previous = output_P_T(); - break; - case 0x6: - previous = output_PS_(); - break; - case 0x7: - previous = output_PST(); - break; - case 0x8: - previous = noise_output_cached; - break; - case 0x9: - previous = outputN__T(); - break; - case 0xa: - previous = outputN_S_(); - break; - case 0xb: - previous = outputN_ST(); - break; - case 0xc: - previous = outputNP__(); - break; - case 0xd: - previous = outputNP_T(); - break; - case 0xe: - previous = outputNPS_(); - break; - case 0xf: - previous = outputNPST(); - break; - default: - break; - } - return previous; -} - -#endif // not __WAVE_H__ diff --git a/src/sound/resid-fp/wave6581_PST.cc b/src/sound/resid-fp/wave6581_PST.cc deleted file mode 100644 index 19d2126ef6..0000000000 --- a/src/sound/resid-fp/wave6581_PST.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave6581_PST[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, -/* 0x7f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -/* 0x7f8: */ 0x00, 0x00, 0x00, 0x78, 0x78, 0x7e, 0x7f, 0x7f, -/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, -/* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, -/* 0xff8: */ 0x00, 0x00, 0x00, 0x78, 0x78, 0x7e, 0x7f, 0x7f, -}; diff --git a/src/sound/resid-fp/wave6581_PST.dat b/src/sound/resid-fp/wave6581_PST.dat deleted file mode 100644 index 5afe75e22e..0000000000 Binary files a/src/sound/resid-fp/wave6581_PST.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave6581_PS_.cc b/src/sound/resid-fp/wave6581_PS_.cc deleted file mode 100644 index bf133e542e..0000000000 --- a/src/sound/resid-fp/wave6581_PS_.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave6581_PS_[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, -/* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3f, -/* 0x3f8: */ 0x00, 0x30, 0x38, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, -/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5f, -/* 0x5f8: */ 0x00, 0x40, 0x40, 0x5f, 0x5c, 0x5f, 0x5f, 0x5f, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6b, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x6d, -/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x6e8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x6e, -/* 0x6f0: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x6f, -/* 0x6f8: */ 0x00, 0x60, 0x60, 0x6f, 0x60, 0x6f, 0x6f, 0x6f, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x738: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x60, 0x73, -/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x758: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x75, -/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x768: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x76, -/* 0x770: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x77, -/* 0x778: */ 0x00, 0x70, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, -/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x798: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x79, -/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x7a8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x70, 0x7a, -/* 0x7b0: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7b, -/* 0x7b8: */ 0x40, 0x70, 0x70, 0x7b, 0x78, 0x7b, 0x7b, 0x7b, -/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -/* 0x7c8: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7c, -/* 0x7d0: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7d, -/* 0x7d8: */ 0x40, 0x70, 0x78, 0x7d, 0x78, 0x7d, 0x7d, 0x7d, -/* 0x7e0: */ 0x00, 0x40, 0x40, 0x78, 0x60, 0x78, 0x78, 0x7e, -/* 0x7e8: */ 0x60, 0x78, 0x78, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e, -/* 0x7f0: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, -/* 0x7f8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, -/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f, -/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, -/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, -/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, -/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3f, -/* 0xbf8: */ 0x00, 0x30, 0x38, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, -/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, -/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5f, -/* 0xdf8: */ 0x00, 0x40, 0x40, 0x5f, 0x5c, 0x5f, 0x5f, 0x5f, -/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, -/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6b, -/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6d, -/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0xee8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x6e, -/* 0xef0: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x6f, -/* 0xef8: */ 0x00, 0x60, 0x60, 0x6f, 0x60, 0x6f, 0x6f, 0x6f, -/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0xf38: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x60, 0x73, -/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0xf58: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x75, -/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0xf68: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x76, -/* 0xf70: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x77, -/* 0xf78: */ 0x00, 0x70, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, -/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0xf98: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x79, -/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0xfa8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x70, 0x7a, -/* 0xfb0: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7b, -/* 0xfb8: */ 0x40, 0x70, 0x70, 0x7b, 0x78, 0x7b, 0x7b, 0x7b, -/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, -/* 0xfc8: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7c, -/* 0xfd0: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7d, -/* 0xfd8: */ 0x40, 0x70, 0x78, 0x7d, 0x78, 0x7d, 0x7d, 0x7d, -/* 0xfe0: */ 0x00, 0x40, 0x40, 0x78, 0x60, 0x78, 0x78, 0x7e, -/* 0xfe8: */ 0x60, 0x78, 0x78, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e, -/* 0xff0: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7c, 0x7f, 0x7f, 0x7f, -/* 0xff8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, -}; diff --git a/src/sound/resid-fp/wave6581_PS_.dat b/src/sound/resid-fp/wave6581_PS_.dat deleted file mode 100644 index ea2fb9c539..0000000000 Binary files a/src/sound/resid-fp/wave6581_PS_.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave6581_P_T.cc b/src/sound/resid-fp/wave6581_P_T.cc deleted file mode 100644 index 30736169ea..0000000000 --- a/src/sound/resid-fp/wave6581_P_T.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave6581_P_T[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x38, 0x3f, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x5f, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x378: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x6f, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x70, 0x77, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7b, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, -/* 0x3e8: */ 0x00, 0x40, 0x40, 0x70, 0x60, 0x70, 0x78, 0x7d, -/* 0x3f0: */ 0x00, 0x40, 0x60, 0x78, 0x60, 0x78, 0x78, 0x7e, -/* 0x3f8: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x9f, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x578: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0xa0, 0xa0, 0xaf, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0, -/* 0x5b8: */ 0x00, 0x80, 0x80, 0xa0, 0x80, 0xa0, 0xb0, 0xb7, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0, -/* 0x5d8: */ 0x00, 0x80, 0x80, 0xa0, 0x80, 0xb0, 0xb0, 0xbb, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xb0, -/* 0x5e8: */ 0x80, 0x80, 0x80, 0xb0, 0x80, 0xb0, 0xb8, 0xbd, -/* 0x5f0: */ 0x80, 0x80, 0x80, 0xb8, 0xa0, 0xb8, 0xb8, 0xbe, -/* 0x5f8: */ 0xa0, 0xb8, 0xbc, 0xbf, 0xbe, 0xbf, 0xbf, 0xbf, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, -/* 0x670: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, -/* 0x678: */ 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x698: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0xc0, 0xc0, -/* 0x6b8: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd7, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, -/* 0x6d0: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, -/* 0x6d8: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd0, 0xdb, -/* 0x6e0: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xd0, -/* 0x6e8: */ 0x80, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd8, 0xdd, -/* 0x6f0: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd8, 0xd8, 0xde, -/* 0x6f8: */ 0xc0, 0xd8, 0xdc, 0xdf, 0xdc, 0xdf, 0xdf, 0xdf, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x718: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xe0, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x728: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, -/* 0x730: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, -/* 0x738: */ 0x80, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe7, -/* 0x740: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, -/* 0x748: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, -/* 0x750: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, -/* 0x758: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xeb, -/* 0x760: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, -/* 0x768: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xed, -/* 0x770: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, 0xe8, 0xee, -/* 0x778: */ 0xe0, 0xe8, 0xec, 0xef, 0xec, 0xef, 0xef, 0xef, -/* 0x780: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0x788: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, -/* 0x790: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, -/* 0x798: */ 0xc0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf3, -/* 0x7a0: */ 0x80, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xf0, -/* 0x7a8: */ 0xc0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf5, -/* 0x7b0: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf6, -/* 0x7b8: */ 0xf0, 0xf0, 0xf4, 0xf7, 0xf4, 0xf7, 0xf7, 0xf7, -/* 0x7c0: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, -/* 0x7c8: */ 0xe0, 0xe0, 0xe0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf9, -/* 0x7d0: */ 0xe0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xfa, -/* 0x7d8: */ 0xf0, 0xf8, 0xf8, 0xfb, 0xf8, 0xfb, 0xfb, 0xfb, -/* 0x7e0: */ 0xe0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xfc, 0xfc, -/* 0x7e8: */ 0xf8, 0xfc, 0xfc, 0xfd, 0xfc, 0xfd, 0xfd, 0xfd, -/* 0x7f0: */ 0xf8, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, -/* 0x7f8: */ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -/* 0x800: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, -/* 0x808: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xf8, -/* 0x810: */ 0xfd, 0xfd, 0xfd, 0xfc, 0xfd, 0xfc, 0xfc, 0xf8, -/* 0x818: */ 0xfc, 0xfc, 0xfc, 0xf0, 0xf8, 0xf0, 0xf0, 0xe0, -/* 0x820: */ 0xfb, 0xfb, 0xfb, 0xf8, 0xfb, 0xf8, 0xf8, 0xf0, -/* 0x828: */ 0xfa, 0xf8, 0xf8, 0xf0, 0xf8, 0xf0, 0xf0, 0xe0, -/* 0x830: */ 0xf9, 0xf8, 0xf8, 0xf0, 0xf8, 0xf0, 0xe0, 0xe0, -/* 0x838: */ 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, -/* 0x840: */ 0xf7, 0xf7, 0xf7, 0xf4, 0xf7, 0xf4, 0xf0, 0xf0, -/* 0x848: */ 0xf6, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, -/* 0x850: */ 0xf5, 0xf0, 0xf0, 0xe0, 0xf0, 0xe0, 0xe0, 0xc0, -/* 0x858: */ 0xf0, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xc0, 0x80, -/* 0x860: */ 0xf3, 0xf0, 0xf0, 0xe0, 0xf0, 0xe0, 0xe0, 0xc0, -/* 0x868: */ 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, -/* 0x870: */ 0xf0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, -/* 0x878: */ 0xc0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0x880: */ 0xef, 0xef, 0xef, 0xec, 0xef, 0xec, 0xe8, 0xe0, -/* 0x888: */ 0xee, 0xe8, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, -/* 0x890: */ 0xed, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, -/* 0x898: */ 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, -/* 0x8a0: */ 0xeb, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, -/* 0x8a8: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, -/* 0x8b0: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, -/* 0x8b8: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0x8c0: */ 0xe7, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xc0, 0x80, -/* 0x8c8: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, -/* 0x8d0: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, -/* 0x8d8: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x900: */ 0xdf, 0xdf, 0xdf, 0xdc, 0xdf, 0xdc, 0xd8, 0xc0, -/* 0x908: */ 0xde, 0xd8, 0xd8, 0xc0, 0xd8, 0xc0, 0xc0, 0xc0, -/* 0x910: */ 0xdd, 0xd8, 0xd0, 0xc0, 0xd0, 0xc0, 0xc0, 0x80, -/* 0x918: */ 0xd0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, -/* 0x920: */ 0xdb, 0xd0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, -/* 0x928: */ 0xc0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, -/* 0x930: */ 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0x938: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x940: */ 0xd7, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, -/* 0x948: */ 0xc0, 0xc0, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0x950: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0x958: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0x968: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x980: */ 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, -/* 0x988: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0x990: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c0: */ 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa00: */ 0xbf, 0xbf, 0xbf, 0xbe, 0xbf, 0xbc, 0xbc, 0xa0, -/* 0xa08: */ 0xbe, 0xbc, 0xb8, 0xa0, 0xb8, 0xa0, 0x80, 0x80, -/* 0xa10: */ 0xbd, 0xb8, 0xb0, 0x80, 0xb0, 0x80, 0x80, 0x80, -/* 0xa18: */ 0xb0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0xa20: */ 0xbb, 0xb0, 0xb0, 0x80, 0xa0, 0x80, 0x80, 0x00, -/* 0xa28: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0xa30: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa40: */ 0xb7, 0xb0, 0xa0, 0x80, 0xa0, 0x80, 0x80, 0x00, -/* 0xa48: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa80: */ 0xaf, 0xa0, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x00, -/* 0xa88: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb00: */ 0x9f, 0x90, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb10: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb40: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb80: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc00: */ 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7c, 0x7c, 0x70, -/* 0xc08: */ 0x7e, 0x7c, 0x78, 0x60, 0x78, 0x60, 0x60, 0x00, -/* 0xc10: */ 0x7d, 0x78, 0x78, 0x60, 0x70, 0x40, 0x40, 0x00, -/* 0xc18: */ 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc20: */ 0x7b, 0x78, 0x70, 0x40, 0x70, 0x40, 0x00, 0x00, -/* 0xc28: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc30: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x77, 0x70, 0x70, 0x00, 0x60, 0x00, 0x00, 0x00, -/* 0xc48: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc80: */ 0x6f, 0x60, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd00: */ 0x5f, 0x58, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe00: */ 0x3f, 0x3c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xff8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff --git a/src/sound/resid-fp/wave6581_P_T.dat b/src/sound/resid-fp/wave6581_P_T.dat deleted file mode 100644 index 1cc8874da7..0000000000 Binary files a/src/sound/resid-fp/wave6581_P_T.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave6581__ST.cc b/src/sound/resid-fp/wave6581__ST.cc deleted file mode 100644 index d193550f26..0000000000 --- a/src/sound/resid-fp/wave6581__ST.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave6581__ST[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3f0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, -/* 0x3f8: */ 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x3f, 0x3f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7e0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, -/* 0x7e8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, -/* 0x7f0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, -/* 0x7f8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, -/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, -/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, -/* 0xbf8: */ 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x3f, 0x3f, -/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f, -/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, -/* 0xfe8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, -/* 0xff0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, -/* 0xff8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, -}; diff --git a/src/sound/resid-fp/wave6581__ST.dat b/src/sound/resid-fp/wave6581__ST.dat deleted file mode 100644 index 2e5d9872c4..0000000000 Binary files a/src/sound/resid-fp/wave6581__ST.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave8580_PST.cc b/src/sound/resid-fp/wave8580_PST.cc deleted file mode 100644 index 51ae21612d..0000000000 --- a/src/sound/resid-fp/wave8580_PST.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave8580_PST[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, -/* 0x7f0: */ 0x60, 0x20, 0x70, 0x70, 0x70, 0x70, 0x70, 0x78, -/* 0x7f8: */ 0x78, 0x78, 0x7c, 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, -/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1e, 0x3f, -/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xdf8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8c, 0x9f, -/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe78: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe80: */ 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, -/* 0xe88: */ 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xea0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xea8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xeb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xeb8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xec0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xec8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xed0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xed8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xee0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xee8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, -/* 0xef0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xef8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf, -/* 0xf00: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf08: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf10: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf18: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf20: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf28: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf30: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf38: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf40: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf48: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf50: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf58: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf60: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf68: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, -/* 0xf70: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf78: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe3, -/* 0xf80: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf88: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf90: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf98: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xfa0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xfa8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xfb0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, -/* 0xfb8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfc0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfc8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfd0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfd8: */ 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfe0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfe8: */ 0xf8, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, -/* 0xff0: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, -/* 0xff8: */ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; diff --git a/src/sound/resid-fp/wave8580_PST.dat b/src/sound/resid-fp/wave8580_PST.dat deleted file mode 100644 index 22706cf250..0000000000 Binary files a/src/sound/resid-fp/wave8580_PST.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave8580_PS_.cc b/src/sound/resid-fp/wave8580_PS_.cc deleted file mode 100644 index e33a2cee55..0000000000 --- a/src/sound/resid-fp/wave8580_PS_.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave8580_PS_[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x1f, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, -/* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, -/* 0x3f8: */ 0x00, 0x0c, 0x1c, 0x3f, 0x1e, 0x3f, 0x3f, 0x3f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, -/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, -/* 0x5f8: */ 0x00, 0x00, 0x00, 0x5f, 0x0c, 0x5f, 0x5f, 0x5f, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, -/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, -/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, -/* 0x6f8: */ 0x00, 0x40, 0x40, 0x6f, 0x40, 0x6f, 0x6f, 0x6f, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, -/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x61, -/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x768: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x70, -/* 0x770: */ 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, -/* 0x778: */ 0x40, 0x60, 0x60, 0x77, 0x60, 0x77, 0x77, 0x77, -/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, -/* 0x798: */ 0x00, 0x40, 0x40, 0x60, 0x40, 0x60, 0x60, 0x79, -/* 0x7a0: */ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x60, -/* 0x7a8: */ 0x40, 0x40, 0x40, 0x60, 0x60, 0x60, 0x60, 0x78, -/* 0x7b0: */ 0x40, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, -/* 0x7b8: */ 0x60, 0x70, 0x70, 0x78, 0x70, 0x79, 0x7b, 0x7b, -/* 0x7c0: */ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, -/* 0x7c8: */ 0x60, 0x60, 0x60, 0x70, 0x60, 0x70, 0x70, 0x7c, -/* 0x7d0: */ 0x60, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x7c, -/* 0x7d8: */ 0x70, 0x78, 0x78, 0x7c, 0x78, 0x7c, 0x7c, 0x7d, -/* 0x7e0: */ 0x70, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x7c, -/* 0x7e8: */ 0x78, 0x7c, 0x7c, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e, -/* 0x7f0: */ 0x7c, 0x7c, 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, -/* 0x7f8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, -/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, -/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, -/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, -/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, -/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x8e, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x8f, -/* 0x9f8: */ 0x80, 0x80, 0x80, 0x9f, 0x80, 0x9f, 0x9f, 0x9f, -/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x87, -/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x83, -/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, -/* 0xad8: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, -/* 0xae0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xae8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x84, -/* 0xaf0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x87, -/* 0xaf8: */ 0x80, 0x80, 0x80, 0x87, 0x80, 0x8f, 0xaf, 0xaf, -/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb20: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, -/* 0xb28: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb30: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb38: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x83, -/* 0xb40: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb48: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb50: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb58: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, -/* 0xb60: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb68: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, -/* 0xb70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, -/* 0xb78: */ 0x80, 0x80, 0x80, 0xa0, 0x80, 0xa3, 0xb7, 0xb7, -/* 0xb80: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xb1, -/* 0xba0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xba8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xb0, -/* 0xbb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xb0, -/* 0xbb8: */ 0x80, 0xa0, 0xa0, 0xb0, 0xa0, 0xb8, 0xb9, 0xbb, -/* 0xbc0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, -/* 0xbc8: */ 0x80, 0x80, 0x80, 0xa0, 0x80, 0xa0, 0xa0, 0xb8, -/* 0xbd0: */ 0x80, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xb8, -/* 0xbd8: */ 0xa0, 0xb0, 0xb0, 0xb8, 0xb0, 0xbc, 0xbc, 0xbd, -/* 0xbe0: */ 0xa0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb8, 0xb8, 0xbc, -/* 0xbe8: */ 0xb0, 0xb8, 0xb8, 0xbc, 0xb8, 0xbc, 0xbe, 0xbe, -/* 0xbf0: */ 0xb8, 0xbc, 0xbc, 0xbe, 0xbc, 0xbe, 0xbe, 0xbf, -/* 0xbf8: */ 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, -/* 0xc00: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, -/* 0xc08: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, -/* 0xc10: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc18: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc20: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc28: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc30: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc38: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, -/* 0xc40: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc48: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc50: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc58: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc60: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc68: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc78: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc7, -/* 0xc80: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xc98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xca0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xca8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xcb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xcb8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc3, -/* 0xcc0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xcc8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0xcd0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0xcd8: */ 0x80, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc1, -/* 0xce0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0xce8: */ 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xcf0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc7, -/* 0xcf8: */ 0xc0, 0xc0, 0xc0, 0xc7, 0xc0, 0xcf, 0xcf, 0xcf, -/* 0xd00: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xd08: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xd10: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xd18: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0xd20: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xd28: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0xd30: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, -/* 0xd38: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc3, -/* 0xd40: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0xd48: */ 0x80, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, -/* 0xd50: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd58: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, -/* 0xd60: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd68: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd70: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd78: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc7, 0xd7, -/* 0xd80: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd88: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd90: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xd98: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xda0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xda8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, -/* 0xdb0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, -/* 0xdb8: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd8, 0xdb, -/* 0xdc0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xdc8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, -/* 0xdd0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, -/* 0xdd8: */ 0xc0, 0xc0, 0xc0, 0xd8, 0xd0, 0xd8, 0xd8, 0xdd, -/* 0xde0: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd0, 0xdc, -/* 0xde8: */ 0xd0, 0xd8, 0xd8, 0xdc, 0xd8, 0xdc, 0xdc, 0xde, -/* 0xdf0: */ 0xd8, 0xdc, 0xdc, 0xde, 0xdc, 0xde, 0xde, 0xdf, -/* 0xdf8: */ 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, -/* 0xe00: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe08: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe10: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe18: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe20: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe28: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe30: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe38: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe3, -/* 0xe40: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe48: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xe50: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, -/* 0xe58: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe1, -/* 0xe60: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, -/* 0xe68: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xe70: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xe78: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe3, 0xe7, -/* 0xe80: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, -/* 0xe88: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, -/* 0xe90: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, -/* 0xe98: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xea0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xea8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xeb0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xeb8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xeb, -/* 0xec0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xec8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xed0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xed8: */ 0xe0, 0xe0, 0xe0, 0xe8, 0xe0, 0xe8, 0xe8, 0xed, -/* 0xee0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xec, -/* 0xee8: */ 0xe0, 0xe0, 0xe0, 0xec, 0xe8, 0xec, 0xec, 0xee, -/* 0xef0: */ 0xe8, 0xe8, 0xe8, 0xec, 0xec, 0xee, 0xee, 0xef, -/* 0xef8: */ 0xec, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, -/* 0xf00: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf08: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf10: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf18: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, -/* 0xf20: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, -/* 0xf28: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf0, -/* 0xf30: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf38: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf3, -/* 0xf40: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf48: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf50: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf58: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf5, -/* 0xf60: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf68: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xf4, 0xf6, -/* 0xf70: */ 0xf0, 0xf0, 0xf0, 0xf4, 0xf0, 0xf4, 0xf6, 0xf7, -/* 0xf78: */ 0xf4, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, -/* 0xf80: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, -/* 0xf88: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, -/* 0xf90: */ 0xf0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf8, -/* 0xf98: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, -/* 0xfa0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfa8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfa, -/* 0xfb0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfb, -/* 0xfb8: */ 0xf8, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, -/* 0xfc0: */ 0xf8, 0xf8, 0xf8, 0xfc, 0xf8, 0xfc, 0xfc, 0xfc, -/* 0xfc8: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, -/* 0xfd0: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, -/* 0xfd8: */ 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, -/* 0xfe0: */ 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, -/* 0xfe8: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, -/* 0xff0: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -/* 0xff8: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; diff --git a/src/sound/resid-fp/wave8580_PS_.dat b/src/sound/resid-fp/wave8580_PS_.dat deleted file mode 100644 index 9a20a9eee6..0000000000 Binary files a/src/sound/resid-fp/wave8580_PS_.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave8580_P_T.cc b/src/sound/resid-fp/wave8580_P_T.cc deleted file mode 100644 index 206a917281..0000000000 --- a/src/sound/resid-fp/wave8580_P_T.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave8580_P_T[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x3c, 0x3f, 0x3f, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x5e, 0x5f, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x378: */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x60, 0x60, 0x6f, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x60, -/* 0x3b8: */ 0x40, 0x40, 0x60, 0x60, 0x60, 0x60, 0x70, 0x77, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, -/* 0x3c8: */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x60, 0x60, 0x60, -/* 0x3d0: */ 0x40, 0x40, 0x40, 0x60, 0x60, 0x60, 0x60, 0x70, -/* 0x3d8: */ 0x60, 0x60, 0x60, 0x70, 0x70, 0x70, 0x78, 0x7b, -/* 0x3e0: */ 0x60, 0x60, 0x60, 0x70, 0x60, 0x70, 0x70, 0x70, -/* 0x3e8: */ 0x70, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x7c, -/* 0x3f0: */ 0x78, 0x78, 0x78, 0x7c, 0x78, 0x7c, 0x7c, 0x7e, -/* 0x3f8: */ 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x4d8: */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x4e8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x4f0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x4f8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8e, 0x9f, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, -/* 0x530: */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x538: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x540: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, -/* 0x548: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x550: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x558: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x560: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x568: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x570: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x578: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xaf, -/* 0x580: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x588: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x590: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x598: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x5a0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x5a8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x5b0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x5b8: */ 0x80, 0x80, 0x80, 0xa0, 0xa0, 0xa0, 0xa0, 0xb7, -/* 0x5c0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x5c8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, -/* 0x5d0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, 0xa0, -/* 0x5d8: */ 0xa0, 0xa0, 0xa0, 0xb0, 0xa0, 0xb0, 0xb0, 0xbb, -/* 0x5e0: */ 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xb0, 0xb0, -/* 0x5e8: */ 0xa0, 0xb0, 0xb0, 0xb8, 0xb0, 0xb8, 0xb8, 0xbc, -/* 0x5f0: */ 0xb0, 0xb8, 0xb8, 0xb8, 0xb8, 0xbc, 0xbc, 0xbe, -/* 0x5f8: */ 0xbc, 0xbc, 0xbe, 0xbf, 0xbe, 0xbf, 0xbf, 0xbf, -/* 0x600: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x608: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x610: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x618: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x620: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x628: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x630: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x638: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, -/* 0x640: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x648: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x650: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, -/* 0x658: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x660: */ 0x80, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, -/* 0x668: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x670: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x678: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf, -/* 0x680: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, -/* 0x688: */ 0xc0, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x690: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x698: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6a0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6a8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6b0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6b8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd7, -/* 0x6c0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6c8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6d0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x6d8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd0, 0xd9, -/* 0x6e0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, -/* 0x6e8: */ 0xc0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd8, 0xd8, 0xdc, -/* 0x6f0: */ 0xd0, 0xd0, 0xd8, 0xd8, 0xd8, 0xdc, 0xdc, 0xde, -/* 0x6f8: */ 0xdc, 0xdc, 0xde, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, -/* 0x700: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x708: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x710: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x718: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, -/* 0x720: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, -/* 0x728: */ 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x730: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x738: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe7, -/* 0x740: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x748: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x750: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x758: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, -/* 0x760: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x768: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, 0xec, -/* 0x770: */ 0xe0, 0xe0, 0xe0, 0xe8, 0xe8, 0xe8, 0xec, 0xee, -/* 0x778: */ 0xec, 0xec, 0xec, 0xee, 0xee, 0xef, 0xef, 0xef, -/* 0x780: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x788: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, -/* 0x790: */ 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x798: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x7a0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x7a8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, -/* 0x7b0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, -/* 0x7b8: */ 0xf0, 0xf4, 0xf4, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, -/* 0x7c0: */ 0xf0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf8, -/* 0x7c8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0x7d0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0x7d8: */ 0xf8, 0xf8, 0xf8, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, -/* 0x7e0: */ 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, -/* 0x7e8: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, -/* 0x7f0: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, -/* 0x7f8: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -/* 0x800: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -/* 0x808: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, -/* 0x810: */ 0xfd, 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, -/* 0x818: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, -/* 0x820: */ 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xf8, 0xf8, 0xf8, -/* 0x828: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0x830: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0x838: */ 0xf8, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x840: */ 0xf7, 0xf7, 0xf7, 0xf6, 0xf6, 0xf4, 0xf4, 0xf0, -/* 0x848: */ 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x850: */ 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x858: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x860: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0x868: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, -/* 0x870: */ 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x878: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x880: */ 0xef, 0xef, 0xef, 0xee, 0xee, 0xec, 0xec, 0xe8, -/* 0x888: */ 0xee, 0xec, 0xe8, 0xe8, 0xe8, 0xe0, 0xe0, 0xe0, -/* 0x890: */ 0xec, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x898: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8a0: */ 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8a8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8b0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8b8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8c0: */ 0xe7, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8c8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0x8d0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, -/* 0x8d8: */ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x8e0: */ 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x8e8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x8f0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x8f8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x900: */ 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xde, 0xdc, 0xdc, -/* 0x908: */ 0xde, 0xdc, 0xdc, 0xd8, 0xd8, 0xd8, 0xd0, 0xd0, -/* 0x910: */ 0xdc, 0xd8, 0xd8, 0xd0, 0xd0, 0xd0, 0xd0, 0xc0, -/* 0x918: */ 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x920: */ 0xd9, 0xd0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x928: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x930: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x938: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x940: */ 0xd7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x948: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x950: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x958: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x960: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x968: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x970: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, -/* 0x978: */ 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x980: */ 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x988: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x990: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0x998: */ 0xc0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x80, -/* 0x9a0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, -/* 0x9a8: */ 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9b0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9b8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9c0: */ 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9c8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9d0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9d8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9e0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9e8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9f0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0x9f8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa00: */ 0xbf, 0xbf, 0xbf, 0xbe, 0xbf, 0xbe, 0xbc, 0xbc, -/* 0xa08: */ 0xbe, 0xbc, 0xbc, 0xb8, 0xb8, 0xb8, 0xb8, 0xb0, -/* 0xa10: */ 0xbc, 0xb8, 0xb8, 0xb0, 0xb8, 0xb0, 0xb0, 0xb0, -/* 0xa18: */ 0xb0, 0xb0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, -/* 0xa20: */ 0xbb, 0xb0, 0xb0, 0xa0, 0xb0, 0xa0, 0xa0, 0xa0, -/* 0xa28: */ 0xa0, 0xa0, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa30: */ 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa38: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa40: */ 0xb7, 0xb0, 0xa0, 0xa0, 0xa0, 0x80, 0x80, 0x80, -/* 0xa48: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa50: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa58: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa60: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa68: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa78: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa80: */ 0xaf, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xa98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xaa0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xaa8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xab0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xab8: */ 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0xac0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xac8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, -/* 0xad0: */ 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb00: */ 0x9f, 0x9e, 0x88, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb08: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb10: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xb18: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb40: */ 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb80: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc00: */ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7c, -/* 0xc08: */ 0x7e, 0x7c, 0x7c, 0x78, 0x7c, 0x78, 0x78, 0x78, -/* 0xc10: */ 0x7c, 0x78, 0x78, 0x78, 0x78, 0x70, 0x70, 0x70, -/* 0xc18: */ 0x78, 0x70, 0x70, 0x60, 0x70, 0x60, 0x60, 0x60, -/* 0xc20: */ 0x7b, 0x78, 0x70, 0x70, 0x70, 0x60, 0x60, 0x60, -/* 0xc28: */ 0x70, 0x60, 0x60, 0x60, 0x60, 0x40, 0x40, 0x40, -/* 0xc30: */ 0x60, 0x60, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, -/* 0xc38: */ 0x40, 0x40, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x77, 0x70, 0x60, 0x60, 0x60, 0x60, 0x40, 0x40, -/* 0xc48: */ 0x60, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc80: */ 0x6f, 0x64, 0x60, 0x40, 0x40, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd00: */ 0x5f, 0x5e, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe00: */ 0x3f, 0x3f, 0x3e, 0x00, 0x1c, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf00: */ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xff8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; diff --git a/src/sound/resid-fp/wave8580_P_T.dat b/src/sound/resid-fp/wave8580_P_T.dat deleted file mode 100644 index 5423dd9ac0..0000000000 Binary files a/src/sound/resid-fp/wave8580_P_T.dat and /dev/null differ diff --git a/src/sound/resid-fp/wave8580__ST.cc b/src/sound/resid-fp/wave8580__ST.cc deleted file mode 100644 index cfe583786f..0000000000 --- a/src/sound/resid-fp/wave8580__ST.cc +++ /dev/null @@ -1,536 +0,0 @@ -// --------------------------------------------------------------------------- -// This file is part of reSID, a MOS6581 SID emulator engine. -// Copyright (C) 2004 Dag Lem -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// --------------------------------------------------------------------------- - -#include "wave.h" - -reg8 WaveformGeneratorFP::wave8580__ST[] = -{ -/* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x1f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, -/* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x3f0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, -/* 0x3f8: */ 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, -/* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x5f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f, -/* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x7e0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, -/* 0x7e8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, -/* 0x7f0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3e, -/* 0x7f8: */ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, -/* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0x9f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, -/* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xbf0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, -/* 0xbf8: */ 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x3f, -/* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, -/* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, -/* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, -/* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xdf8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x1f, 0x1f, -/* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x83, 0x83, -/* 0xe80: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xe98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xea0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xea8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xeb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xeb8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xec0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xec8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xed0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xed8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xee0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xee8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xef0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -/* 0xef8: */ 0x80, 0x80, 0x80, 0x80, 0x87, 0x87, 0x87, 0x8f, -/* 0xf00: */ 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, -/* 0xf08: */ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf10: */ 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf18: */ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, -/* 0xf20: */ 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, -/* 0xf28: */ 0xe0, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, -/* 0xf30: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf38: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf40: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf48: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf50: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf58: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf60: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf68: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf70: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, -/* 0xf78: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe3, 0xe3, -/* 0xf80: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf88: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf90: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xf98: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfa0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfa8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfb0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -/* 0xfb8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, -/* 0xfc0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfc8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfd0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfd8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, -/* 0xfe0: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, -/* 0xfe8: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, -/* 0xff0: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, -/* 0xff8: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -}; diff --git a/src/sound/resid-fp/wave8580__ST.dat b/src/sound/resid-fp/wave8580__ST.dat deleted file mode 100644 index f30002ceb0..0000000000 Binary files a/src/sound/resid-fp/wave8580__ST.dat and /dev/null differ diff --git a/src/sound/snd_ac97_codec.c b/src/sound/snd_ac97_codec.c index d302db6ae3..ae87ce8709 100644 --- a/src/sound/snd_ac97_codec.c +++ b/src/sound/snd_ac97_codec.c @@ -316,7 +316,7 @@ ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val) val = (val & i) | (prev & ~i); /* Update status bits to reflect powerdowns. */ - val = (val & ~0x000f) | (~(val >> 8) & 0x000f); + val = (val & ~0x300f) | (~(val >> 8) & 0x000f); /* also clear write-only PR4 and PR5 */ if (val & 0x0800) /* PR3 clears both ANL and REF */ val &= ~0x0004; break; @@ -527,7 +527,7 @@ ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r) /* Apply full mute and powerdowns. */ int full_mute = (reg < 0x36); if ((full_mute && (val & AC97_MUTE)) || /* full mute */ - (dev->regs[0x26 >> 1] & 0x3e00) || /* DAC powerdown */ + (dev->regs[0x26 >> 1] & 0x0e00) || /* DAC powerdown */ ((reg == 0x38) && (dev->regs[0x2a >> 1] & AC97_PRJ))) { /* surround DAC powerdown */ *l = 0; *r = 0; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 488dcb8a6a..8f62d04175 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -791,8 +791,8 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv) adgold_update(adgold); for (c = 0; c < len * 2; c += 2) { - adgold_buffer[c] += ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4; - adgold_buffer[c + 1] += ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4; + adgold_buffer[c] = ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4; + adgold_buffer[c + 1] = ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4; } if (adgold->surround_enabled) @@ -904,7 +904,6 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv) int c; const int32_t *opl_buf = adgold->opl.update(adgold->opl.priv); - adgold_update(adgold); for (c = 0; c < len * 2; c += 2) { adgold_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2; diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index 1405d8769a..f8c14e06f6 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Ensoniq AudioPCI (ES1371) emulation. + * Ensoniq AudioPCI family emulation. * * * @@ -15,7 +15,7 @@ * Miran Grca, * * Copyright 2008-2021 Sarah Walker. - * Copyright 2021 RichardG. + * Copyright 2021-2024 RichardG. * Copyright 2021 Miran Grca. */ #include @@ -50,6 +50,9 @@ typedef struct es1371_t { uint8_t pci_command; uint8_t pci_serr; + uint8_t subsys_lock; + uint8_t subsys_id[4]; + uint32_t base_addr; uint8_t int_line; @@ -60,6 +63,7 @@ typedef struct es1371_t { uint32_t int_ctrl; uint32_t int_status; uint32_t legacy_ctrl; + uint32_t spdif_chstatus; void *gameport; int mem_page; @@ -118,6 +122,8 @@ typedef struct es1371_t { int master_vol_r; int pcm_vol_l; int pcm_vol_r; + int pcm_rear_vol_l; + int pcm_rear_vol_r; int cd_vol_l; int cd_vol_r; @@ -126,9 +132,13 @@ typedef struct es1371_t { int pos; int16_t buffer[SOUNDBUFLEN * 2]; - int type; + uint32_t type; } es1371_t; +#define AUDIOPCI_ES1371 0x13710200 +#define AUDIOPCI_ES1373 0x13710400 +#define AUDIOPCI_CT5880 0x58800400 + #define LEGACY_SB_ADDR (1 << 29) #define LEGACY_SSCAPE_ADDR_SHIFT 27 #define LEGACY_CODEC_ADDR_SHIFT 25 @@ -160,6 +170,8 @@ typedef struct es1371_t { #define CODEC_READ (1 << 23) #define CODEC_READY (1 << 31) +#define INT_DAC1_BYPASS (1 << 31) +#define INT_DAC2_BYPASS (1 << 30) #define INT_DAC1_EN (1 << 6) #define INT_DAC2_EN (1 << 5) #define INT_UART_EN (1 << 3) @@ -170,6 +182,9 @@ typedef struct es1371_t { #define SI_P1_INTR_EN (1 << 8) #define INT_STATUS_INTR (1 << 31) +#define INT_STATUS_REAR_B27 (1 << 27) +#define INT_STATUS_REAR_B26 (1 << 26) +#define INT_STATUS_REAR_B24 (1 << 24) #define INT_STATUS_UART (1 << 3) #define INT_STATUS_DAC1 (1 << 2) #define INT_STATUS_DAC2 (1 << 1) @@ -324,13 +339,23 @@ es1371_reset(void *priv) nmi = 0; + /* Default subsystem ID. */ + dev->subsys_lock = 0x00; + *((uint16_t *) &dev->subsys_id[0]) = 0x1274; + *((uint16_t *) &dev->subsys_id[2]) = 0x1371; + /* Interrupt/Chip Select Control Register, Address 00H Addressable as byte, word, longword */ dev->int_ctrl = 0xfcff0000; - /* Interrupt/Chip Select Control Register, Address 00H + /* Interrupt/Chip Select Status Register, Address 04H Addressable as longword only */ - dev->int_status = 0x7ffffec0; + if (dev->type >= AUDIOPCI_CT5880) + dev->int_status = 0x52080ec0; + else if (dev->type >= AUDIOPCI_ES1373) + dev->int_status = 0x7f080ec0; + else + dev->int_status = 0x7ffffec0; /* UART Status Register, Address 09H Addressable as byte only */ @@ -360,6 +385,10 @@ es1371_reset(void *priv) Addressable as byte, word, longword */ dev->legacy_ctrl = 0x0000f801; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + dev->spdif_chstatus = 0xc0200004; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ dev->si_cr = 0xff800000; @@ -655,7 +684,9 @@ es1371_inb(uint16_t port, void *priv) ret = (dev->int_ctrl >> 16) & 0x0f; break; case 0x03: - ret = ((dev->int_ctrl >> 24) & 0x03) | 0xfc; + ret = dev->int_ctrl >> 24; + if (dev->type < AUDIOPCI_ES1373) + ret |= 0xfc; break; /* Interrupt/Chip Select Status Register, Address 04H @@ -724,6 +755,25 @@ es1371_inb(uint16_t port, void *priv) ret = dev->legacy_ctrl >> 24; break; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + case 0x1c: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus & 0xff; + break; + case 0x1d: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus >> 8; + break; + case 0x1e: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus >> 16; + break; + case 0x1f: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus >> 24; + break; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: @@ -760,7 +810,9 @@ es1371_inw(uint16_t port, void *priv) ret = dev->int_ctrl & 0xffff; break; case 0x02: - ret = ((dev->int_ctrl >> 16) & 0x030f) | 0xfc00; + ret = (dev->int_ctrl >> 16) & 0xff0f; + if (dev->type < AUDIOPCI_ES1373) + ret |= 0xfc00; break; /* Memory Page Register, Address 0CH @@ -781,6 +833,17 @@ es1371_inw(uint16_t port, void *priv) ret = dev->legacy_ctrl >> 16; break; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + case 0x1c: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus & 0xffff; + break; + case 0x1e: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus >> 16; + break; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: @@ -849,7 +912,9 @@ es1371_inl(uint16_t port, void *priv) /* Interrupt/Chip Select Control Register, Address 00H Addressable as byte, word, longword */ case 0x00: - ret = (dev->int_ctrl & 0x030fffff) | 0xfc000000; + ret = dev->int_ctrl & 0xff0fffff; + if (ret < AUDIOPCI_ES1373) + ret |= 0xfc000000; break; /* Interrupt/Chip Select Status Register, Address 04H @@ -884,6 +949,13 @@ es1371_inl(uint16_t port, void *priv) ret = (dev->legacy_ctrl & 0xffff07fd) | 0x0000f800; break; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + case 0x1c: + if (dev->type >= AUDIOPCI_ES1373) + ret = dev->spdif_chstatus; + break; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: @@ -960,6 +1032,18 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) gameport_remap(dev->gameport, 0x200 | ((val & 0x03) << 3)); break; + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only, but PCem implements byte access, which + must be for a reason */ + case 0x06: + if (dev->type >= AUDIOPCI_ES1373) + dev->int_status = (dev->int_status & 0xff08ffff) | (val << 16); + break; + case 0x07: + if (dev->type >= AUDIOPCI_CT5880) + dev->int_status = (dev->int_status & 0xd2ffffff) | (val << 24); + break; + /* UART Data Register, Address 08H Addressable as byte only */ case 0x08: @@ -1021,6 +1105,21 @@ es1371_outb(uint16_t port, uint8_t val, void *priv) update_legacy(dev, old_legacy_ctrl); break; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + case 0x1c: + dev->spdif_chstatus = (dev->spdif_chstatus & 0xffffff00) | val; + break; + case 0x1d: + dev->spdif_chstatus = (dev->spdif_chstatus & 0xffff00ff) | (val << 8); + break; + case 0x1e: + dev->spdif_chstatus = (dev->spdif_chstatus & 0xff00ffff) | (val << 16); + break; + case 0x1f: + dev->spdif_chstatus = (dev->spdif_chstatus & 0x00ffffff) | (val << 24); + break; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: @@ -1092,6 +1191,15 @@ es1371_outw(uint16_t port, uint16_t val, void *priv) update_legacy(dev, old_legacy_ctrl); break; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + case 0x1c: + dev->spdif_chstatus = (dev->spdif_chstatus & 0xffff0000) | val; + break; + case 0x1e: + dev->spdif_chstatus = (dev->spdif_chstatus & 0x0000ffff) | (val << 16); + break; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: @@ -1161,6 +1269,10 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) Addressable as longword only */ case 0x04: audiopci_log("[W] STATUS = %08X\n", val); + if (dev->type >= AUDIOPCI_CT5880) + dev->int_status = (dev->int_status & 0xd208ffff) | (val & 0x2df70000); + else if (dev->type >= AUDIOPCI_ES1373) + dev->int_status = (dev->int_status & 0xff08ffff) | (val & 0x00f70000); break; /* Memory Page Register, Address 0CH @@ -1231,6 +1343,7 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); ac97_codec_getattn(dev->codec, 0x18, &dev->pcm_vol_l, &dev->pcm_vol_r); + ac97_codec_getattn(dev->codec, 0x38, &dev->pcm_rear_vol_l, &dev->pcm_rear_vol_r); ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); } break; @@ -1245,6 +1358,12 @@ es1371_outl(uint16_t port, uint32_t val, void *priv) update_legacy(dev, old_legacy_ctrl); break; + /* S/PDIF Channel Status Control Register, Address 1CH + Addressable as byte, word, longword */ + case 0x1c: + dev->spdif_chstatus = val; + break; + /* Serial Interface Control Register, Address 20H Addressable as byte, word, longword */ case 0x20: @@ -1612,9 +1731,9 @@ es1371_pci_read(int func, int addr, void *priv) return 0x12; case 0x02: - return 0x71; /* ES1371 */ + return dev->type >> 16; /* ES1371 */ case 0x03: - return 0x13; + return dev->type >> 24; case 0x04: return dev->pci_command; @@ -1627,7 +1746,7 @@ es1371_pci_read(int func, int addr, void *priv) return 0x00; case 0x08: - return 0x02; /* Revision ID - 0x02 is actual Ensoniq-branded ES1371 */ + return dev->type >> 8; /* Revision ID */ case 0x09: return 0x00; /* Multimedia audio device */ case 0x0a: @@ -1644,14 +1763,8 @@ es1371_pci_read(int func, int addr, void *priv) case 0x13: return dev->base_addr >> 24; - case 0x2c: - return 0x74; /* Subsystem vendor ID */ - case 0x2d: - return 0x12; - case 0x2e: - return 0x71; - case 0x2f: - return 0x13; + case 0x2c ... 0x2f: + return dev->subsys_id[addr & 3]; /* Subsystem vendor ID */ case 0x34: return 0xdc; /* Capabilites pointer */ @@ -1666,6 +1779,11 @@ es1371_pci_read(int func, int addr, void *priv) case 0x3f: return 0x80; /* Maximum latency */ + case 0x40: + if (dev->type >= AUDIOPCI_ES1373) + return dev->subsys_lock; + break; + case 0xdc: return 0x01; /* Capabilities identifier */ case 0xdd: @@ -1732,10 +1850,20 @@ es1371_pci_write(int func, int addr, uint8_t val, void *priv) dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24); break; + case 0x2c ... 0x2f: + if (dev->subsys_lock == 0xea) + dev->subsys_id[addr & 3] = val; + break; + case 0x3c: dev->int_line = val; break; + case 0x40: + if (dev->type >= AUDIOPCI_ES1373) + dev->subsys_lock = val; + break; + case 0xe0: dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03); break; @@ -1941,51 +2069,77 @@ es1371_poll(void *priv) es1371_update(dev); if (dev->int_ctrl & INT_DAC1_EN) { - frac = dev->dac[0].ac & 0x7fff; - idx = dev->dac[0].ac >> 15; - samp1_l = dev->dac[0].filtered_l[idx]; - samp1_r = dev->dac[0].filtered_r[idx]; - samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31]; - samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31]; - - dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; - dev->dac[0].ac += dev->dac[0].vf; - dev->dac[0].ac &= ((32 << 15) - 1); - if ((dev->dac[0].ac >> (15 + 4)) != dev->dac[0].f_pos) { - es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); - dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; - - dev->dac[0].curr_samp_ct--; - if (dev->dac[0].curr_samp_ct < 0) { - dev->int_status |= INT_STATUS_DAC1; - es1371_update_irqs(dev); - dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct; + if ((dev->type >= AUDIOPCI_ES1373) && (dev->int_ctrl & INT_DAC1_BYPASS)) { + /* SRC bypass. */ + if ((dev->dac[0].buffer_pos - dev->dac[0].buffer_pos_end) >= 0) + es1371_fetch(dev, 0); + + dev->dac[0].out_l = dev->dac[0].buffer_l[dev->dac[0].buffer_pos & 63]; + dev->dac[0].out_r = dev->dac[0].buffer_r[dev->dac[0].buffer_pos & 63]; + dev->dac[0].buffer_pos++; + + goto dac0_count; + } else { + frac = dev->dac[0].ac & 0x7fff; + idx = dev->dac[0].ac >> 15; + samp1_l = dev->dac[0].filtered_l[idx]; + samp1_r = dev->dac[0].filtered_r[idx]; + samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31]; + samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31]; + + dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; + dev->dac[0].ac += dev->dac[0].vf; + dev->dac[0].ac &= ((32 << 15) - 1); + if ((dev->dac[0].ac >> (15 + 4)) != dev->dac[0].f_pos) { + es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); + dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; + +dac0_count: + dev->dac[0].curr_samp_ct--; + if (dev->dac[0].curr_samp_ct < 0) { + dev->int_status |= INT_STATUS_DAC1; + es1371_update_irqs(dev); + dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct; + } } } } if (dev->int_ctrl & INT_DAC2_EN) { - frac = dev->dac[1].ac & 0x7fff; - idx = dev->dac[1].ac >> 15; - samp1_l = dev->dac[1].filtered_l[idx]; - samp1_r = dev->dac[1].filtered_r[idx]; - samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31]; - samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31]; - - dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; - dev->dac[1].ac += dev->dac[1].vf; - dev->dac[1].ac &= ((32 << 15) - 1); - if ((dev->dac[1].ac >> (15 + 4)) != dev->dac[1].f_pos) { - es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); - dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; - - dev->dac[1].curr_samp_ct--; - if (dev->dac[1].curr_samp_ct < 0) { - dev->int_status |= INT_STATUS_DAC2; - es1371_update_irqs(dev); - dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct; + if ((dev->type >= AUDIOPCI_ES1373) && (dev->int_ctrl & INT_DAC2_BYPASS)) { + /* SRC bypass. */ + if ((dev->dac[1].buffer_pos - dev->dac[1].buffer_pos_end) >= 0) + es1371_fetch(dev, 1); + + dev->dac[1].out_l = dev->dac[1].buffer_l[dev->dac[1].buffer_pos & 63]; + dev->dac[1].out_r = dev->dac[1].buffer_r[dev->dac[1].buffer_pos & 63]; + dev->dac[1].buffer_pos++; + + goto dac1_count; + } else { + frac = dev->dac[1].ac & 0x7fff; + idx = dev->dac[1].ac >> 15; + samp1_l = dev->dac[1].filtered_l[idx]; + samp1_r = dev->dac[1].filtered_r[idx]; + samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31]; + samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31]; + + dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; + dev->dac[1].ac += dev->dac[1].vf; + dev->dac[1].ac &= ((32 << 15) - 1); + if ((dev->dac[1].ac >> (15 + 4)) != dev->dac[1].f_pos) { + es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); + dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; + +dac1_count: + dev->dac[1].curr_samp_ct--; + if (dev->dac[1].curr_samp_ct < 0) { + dev->int_status |= INT_STATUS_DAC2; + es1371_update_irqs(dev); + dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct; + } } } } @@ -2091,6 +2245,7 @@ es1371_init(const device_t *info) { es1371_t *dev = malloc(sizeof(es1371_t)); memset(dev, 0x00, sizeof(es1371_t)); + dev->type = info->local & 0xffffff00; if (device_get_config_int("receive_input")) midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev); @@ -2101,7 +2256,7 @@ es1371_init(const device_t *info) dev->gameport = gameport_add(&gameport_pnp_device); gameport_remap(dev->gameport, 0x200); - pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev, &dev->pci_slot); + pci_add_card((info->local & 1) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev, &dev->pci_slot); timer_add(&dev->dac[1].timer, es1371_poll, dev, 1); @@ -2111,7 +2266,7 @@ es1371_init(const device_t *info) ac97_codec_count = 1; ac97_codec_id = 0; /* Let the machine decide the codec on onboard implementations. */ - if (!info->local) + if (!(info->local & 1)) device_add(ac97_codec_get(device_get_config_int("codec"))); es1371_reset(dev); @@ -2165,6 +2320,70 @@ static const device_config_t es1371_config[] = { // clang-format on }; +static const device_config_t es1373_config[] = { + // clang-format off + { + .name = "codec", + .description = "Codec", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "Crystal CS4297A", + .value = AC97_CODEC_CS4297A + }, + { + .description = "SigmaTel STAC9721T", + .value = AC97_CODEC_STAC9721 + }, + { + .description = "TriTech TR28023 / Creative CT1297", + .value = AC97_CODEC_TR28023 + }, + { .description = "" } + }, + .default_int = AC97_CODEC_CS4297A + }, + { + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + +static const device_config_t ct5880_config[] = { + // clang-format off + { + .name = "codec", + .description = "Codec", + .type = CONFIG_SELECTION, + .selection = { + { + .description = "SigmaTel STAC9708T", + .value = AC97_CODEC_STAC9708 + }, + { + .description = "SigmaTel STAC9721T (stereo)", + .value = AC97_CODEC_STAC9721 + }, + { .description = "" } + }, + .default_int = AC97_CODEC_STAC9708 + }, + { + .name = "receive_input", + .description = "Receive input (MIDI)", + .type = CONFIG_BINARY, + .default_string = "", + .default_int = 1 + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + static const device_config_t es1371_onboard_config[] = { // clang-format off { @@ -2182,7 +2401,7 @@ const device_t es1371_device = { .name = "Ensoniq AudioPCI (ES1371)", .internal_name = "es1371", .flags = DEVICE_PCI, - .local = 0, + .local = AUDIOPCI_ES1371, .init = es1371_init, .close = es1371_close, .reset = es1371_reset, @@ -2196,7 +2415,63 @@ const device_t es1371_onboard_device = { .name = "Ensoniq AudioPCI (ES1371) (On-Board)", .internal_name = "es1371_onboard", .flags = DEVICE_PCI, - .local = 1, + .local = AUDIOPCI_ES1371 | 1, + .init = es1371_init, + .close = es1371_close, + .reset = es1371_reset, + { .available = NULL }, + .speed_changed = es1371_speed_changed, + .force_redraw = NULL, + .config = es1371_onboard_config +}; + +const device_t es1373_device = { + .name = "Sound Blaster PCI 128 (ES1373)", + .internal_name = "es1373", + .flags = DEVICE_PCI, + .local = AUDIOPCI_ES1373, + .init = es1371_init, + .close = es1371_close, + .reset = es1371_reset, + { .available = NULL }, + .speed_changed = es1371_speed_changed, + .force_redraw = NULL, + .config = es1373_config +}; + +const device_t es1373_onboard_device = { + .name = "Sound Blaster PCI 128 (ES1373) (On-Board)", + .internal_name = "es1373_onboard", + .flags = DEVICE_PCI, + .local = AUDIOPCI_ES1373 | 1, + .init = es1371_init, + .close = es1371_close, + .reset = es1371_reset, + { .available = NULL }, + .speed_changed = es1371_speed_changed, + .force_redraw = NULL, + .config = es1371_onboard_config +}; + +const device_t ct5880_device = { + .name = "Sound Blaster PCI 4.1 (CT5880)", + .internal_name = "ct5880", + .flags = DEVICE_PCI, + .local = AUDIOPCI_CT5880, + .init = es1371_init, + .close = es1371_close, + .reset = es1371_reset, + { .available = NULL }, + .speed_changed = es1371_speed_changed, + .force_redraw = NULL, + .config = ct5880_config +}; + +const device_t ct5880_onboard_device = { + .name = "Sound Blaster PCI 4.1 (CT5880) (On-Board)", + .internal_name = "ct5880_onboard", + .flags = DEVICE_PCI, + .local = AUDIOPCI_CT5880 | 1, .init = es1371_init, .close = es1371_close, .reset = es1371_reset, diff --git a/src/sound/snd_cmi8x38.c b/src/sound/snd_cmi8x38.c index 359563b991..d548763cef 100644 --- a/src/sound/snd_cmi8x38.c +++ b/src/sound/snd_cmi8x38.c @@ -706,11 +706,11 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) case 0x02: /* Reset or start DMA channels if requested. */ - dev->io_regs[addr] = val & 0x03; + dev->io_regs[addr] = val & 0x0f; for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) { if (val & (0x04 << i)) { /* Reset DMA channel. */ - val &= ~(0x01 << i); + dev->io_regs[addr] &= ~(0x01 << i); /* clear enable */ dev->io_regs[0x10] &= ~(0x01 << i); /* clear interrupt */ /* Reset Sound Blaster as well when resetting channel 0. */ @@ -724,15 +724,11 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) } } - /* Clear reset bits. */ - val &= 0x03; - /* Start playback along with DMA channels. */ - if (val & 0x03) + if (dev->io_regs[addr] & 0x03) cmi8x38_start_playback(dev); /* Update interrupts. */ - dev->io_regs[addr] = val; cmi8x38_update_irqs(dev); break; @@ -864,7 +860,7 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) case 0x1b: if (dev->type == CMEDIA_CMI8338) - val &= 0xf0; + val &= 0xf4; /* bit 2 reserved, mpxplay driver expects writable */ else val &= 0xd7; break; @@ -913,6 +909,24 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) dev->sb->opl.write(addr, val, dev->sb->opl.priv); return; + case 0x80 ... 0x83: + case 0x88 ... 0x8b: + dev->io_regs[addr] = val; + dev->dma[(addr & 0x78) >> 3].sample_ptr = *((uint32_t *) &dev->io_regs[addr & 0xfc]); + return; + + case 0x84 ... 0x85: + case 0x8c ... 0x8d: + dev->io_regs[addr] = val; + dev->dma[(addr & 0x78) >> 3].frame_count_dma = dev->dma[(addr & 0x78) >> 3].sample_count_out = *((uint16_t *) &dev->io_regs[addr & 0xfe]) + 1; + return; + + case 0x86 ... 0x87: + case 0x8e ... 0x8f: + dev->io_regs[addr] = val; + dev->dma[(addr & 0x78) >> 3].frame_count_fragment = *((uint16_t *) &dev->io_regs[addr & 0xfe]) + 1; + return; + case 0x92: if (dev->type == CMEDIA_CMI8338) return; @@ -931,7 +945,6 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv) case 0x26: case 0x70: case 0x71: - case 0x80 ... 0x8f: break; default: diff --git a/src/sound/snd_cs423x.c b/src/sound/snd_cs423x.c index 90aa0b0dda..95d183e8f7 100644 --- a/src/sound/snd_cs423x.c +++ b/src/sound/snd_cs423x.c @@ -30,7 +30,9 @@ #include <86box/isapnp.h> #include <86box/midi.h> #include <86box/timer.h> +#include <86box/mem.h> #include <86box/nvr.h> +#include <86box/rom.h> #include <86box/pic.h> #include <86box/sound.h> #include <86box/snd_ad1848.h> @@ -39,6 +41,8 @@ #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#define PNP_ROM_CS4236B "roms/sound/crystal/PNPISA01.BIN" + #define CRYSTAL_NOEEPROM 0x100 enum { @@ -58,7 +62,7 @@ static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0 0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2, 0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13, 0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A }; -static const uint8_t cs4236b_eeprom[] = { +static const uint8_t cs4236b_eeprom[8224] = { // clang-format off /* Chip configuration */ 0x55, 0xbb, /* magic */ @@ -74,59 +78,7 @@ static const uint8_t cs4236b_eeprom[] = { 0x10, 0x03, /* DMA routing */ /* PnP resources */ - 0x0e, 0x63, 0x42, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, /* CSC4236, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x01, /* PnP version 1.0, vendor version 0.1 */ - 0x82, 0x0e, 0x00, 'C', 'r', 'y', 's', 't', 'a', 'l', ' ', 'C', 'o', 'd', 'e' ,'c', 0x00, /* ANSI identifier */ - - 0x15, 0x0e, 0x63, 0x00, 0x00, 0x00, /* logical device CSC0000 */ - 0x82, 0x07, 0x00, 'W', 'S', 'S', '/', 'S', 'B', 0x00, /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x2a, 0x02, 0x28, /* DMA 1, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0x09, 0x28, /* DMA 0/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x22, 0x20, 0x00, /* IRQ 5 */ - 0x47, 0x01, 0x34, 0x05, 0x34, 0x05, 0x04, 0x04, /* I/O 0x534, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */ - 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x10, /* I/O 0x220, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x2a, 0x0a, 0x28, /* DMA 1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */ - 0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */ - 0x47, 0x01, 0x20, 0x02, 0x60, 0x02, 0x20, 0x10, /* I/O 0x220-0x260, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x31, 0x02, /* start dependent functions, sub-optimal */ - 0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */ - 0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */ - 0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x08, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 8-byte alignment, 4 addresses */ - 0x47, 0x01, 0x20, 0x02, 0x00, 0x03, 0x20, 0x10, /* I/O 0x220-0x300, decodes 16-bit, 32-byte alignment, 16 addresses */ - 0x38, /* end dependent functions */ - - 0x15, 0x0e, 0x63, 0x00, 0x01, 0x00, /* logical device CSC0001 */ - 0x82, 0x05, 0x00, 'G', 'A', 'M', 'E', 0x00, /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */ - 0x38, /* end dependent functions */ - - 0x15, 0x0e, 0x63, 0x00, 0x10, 0x00, /* logical device CSC0010 */ - 0x82, 0x05, 0x00, 'C', 'T', 'R', 'L', 0x00, /* ANSI identifier */ - 0x47, 0x01, 0x20, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x120-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */ - - 0x15, 0x0e, 0x63, 0x00, 0x03, 0x00, /* logical device CSC0003 */ - 0x82, 0x04, 0x00, 'M', 'P', 'U', 0x00, /* ANSI identifier */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x22, 0x00, 0x02, /* IRQ 9 */ - 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x08, 0x02, /* I/O 0x330, decodes 16-bit, 8-byte alignment, 2 addresses */ - 0x31, 0x01, /* start dependent functions, acceptable */ - 0x22, 0x00, 0x9a, /* IRQ 9/11/12/15 */ - 0x47, 0x01, 0x30, 0x03, 0x60, 0x03, 0x08, 0x02, /* I/O 0x330-0x360, decodes 16-bit, 8-byte alignment, 2 addresses */ - 0x31, 0x02, /* start dependent functions, sub-optimal */ - 0x47, 0x01, 0x30, 0x03, 0xe0, 0x03, 0x08, 0x02, /* I/O 0x330-0x3E0, decodes 16-bit, 8-byte alignment, 2 addresses */ - 0x38, /* end dependent functions */ - - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ + 0x00 // clang-format on }; @@ -798,6 +750,12 @@ cs423x_init(const device_t *info) /* Load EEPROM contents from template. */ memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom)); + FILE *fp = rom_fopen(PNP_ROM_CS4236B, "rb"); + if (fp) { + (void) !fread(&(dev->eeprom_data[23]), 1, 8201, fp); + fclose(fp); + } + /* Set content size. */ dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8; dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff; @@ -808,6 +766,7 @@ cs423x_init(const device_t *info) dev->eeprom_data[8] = 0x05; dev->eeprom_data[16] = 0x08; dev->eeprom_data[26] = 0x25; + dev->eeprom_data[44] = '5'; dev->nvr_path = "cs4235.nvr"; break; @@ -817,11 +776,13 @@ cs423x_init(const device_t *info) case CRYSTAL_CS4237B: dev->eeprom_data[26] = 0x37; + dev->eeprom_data[44] = '7'; dev->nvr_path = "cs4237b.nvr"; break; case CRYSTAL_CS4238B: dev->eeprom_data[26] = 0x38; + dev->eeprom_data[44] = '8'; dev->nvr_path = "cs4238b.nvr"; break; @@ -886,6 +847,12 @@ cs423x_close(void *priv) free(dev); } +static int +cs423x_available(void) +{ + return rom_present(PNP_ROM_CS4236B); +} + static void cs423x_speed_changed(void *priv) { @@ -902,7 +869,7 @@ const device_t cs4235_device = { .init = cs423x_init, .close = cs423x_close, .reset = cs423x_reset, - { .available = NULL }, + { .available = cs423x_available }, .speed_changed = cs423x_speed_changed, .force_redraw = NULL, .config = NULL @@ -916,7 +883,7 @@ const device_t cs4235_onboard_device = { .init = cs423x_init, .close = cs423x_close, .reset = cs423x_reset, - { .available = NULL }, + { .available = cs423x_available }, .speed_changed = cs423x_speed_changed, .force_redraw = NULL, .config = NULL @@ -930,7 +897,7 @@ const device_t cs4236b_device = { .init = cs423x_init, .close = cs423x_close, .reset = cs423x_reset, - { .available = NULL }, + { .available = cs423x_available }, .speed_changed = cs423x_speed_changed, .force_redraw = NULL, .config = NULL @@ -944,7 +911,7 @@ const device_t cs4237b_device = { .init = cs423x_init, .close = cs423x_close, .reset = cs423x_reset, - { .available = NULL }, + { .available = cs423x_available }, .speed_changed = cs423x_speed_changed, .force_redraw = NULL, .config = NULL @@ -958,7 +925,7 @@ const device_t cs4238b_device = { .init = cs423x_init, .close = cs423x_close, .reset = cs423x_reset, - { .available = NULL }, + { .available = cs423x_available }, .speed_changed = cs423x_speed_changed, .force_redraw = NULL, .config = NULL diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index d0af5c5644..10b6f00dc8 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -16,9 +16,9 @@ #include <86box/pic.h> #include <86box/sound.h> #include <86box/timer.h> -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX # include <86box/snd_ad1848.h> -#endif +#endif /*USE_GUSMAX */ #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> @@ -144,11 +144,11 @@ typedef struct gus_t { uint8_t usrr; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX uint8_t max_ctrl; ad1848_t ad1848; -#endif +#endif /*USE_GUSMAX */ } gus_t; static int gus_gf1_irqs[8] = { -1, 2, 5, 3, 7, 11, 12, 15 }; @@ -256,9 +256,9 @@ writegus(uint16_t addr, uint8_t val, void *priv) int d; int old; uint16_t port; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX uint16_t csioport; -#endif +#endif /*USE_GUSMAX */ if ((addr == 0x388) || (addr == 0x389)) port = addr; @@ -606,10 +606,10 @@ writegus(uint16_t addr, uint8_t val, void *priv) gus->irq_midi = gus->irq; } else gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if (gus->type == GUS_MAX) ad1848_setirq(&gus->ad1848, gus->irq); -#endif +#endif /*USE_GUSMAX */ gus->sb_nmi = val & 0x80; } else { @@ -622,10 +622,10 @@ writegus(uint16_t addr, uint8_t val, void *priv) gus->dma2 = gus->dma; } else gus->dma2 = gus_dmas[(val >> 3) & 7]; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if (gus->type == GUS_MAX) ad1848_setdma(&gus->ad1848, gus->dma2); -#endif +#endif /*USE_GUSMAX */ } break; case 1: @@ -683,7 +683,7 @@ writegus(uint16_t addr, uint8_t val, void *priv) break; case 0x306: case 0x706: -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if (gus->type == GUS_MAX) { if (gus->dma >= 4) val |= 0x10; @@ -703,7 +703,7 @@ writegus(uint16_t addr, uint8_t val, void *priv) } } } -#endif +#endif /*USE_GUSMAX */ break; default: @@ -755,11 +755,11 @@ readgus(uint16_t addr, void *priv) return val; case 0x20F: -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if (gus->type == GUS_MAX) val = 0x02; else -#endif +#endif /*USE_GUSMAX */ val = 0x00; break; @@ -878,11 +878,11 @@ readgus(uint16_t addr, void *priv) break; case 0x306: case 0x706: -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if (gus->type == GUS_MAX) val = 0x0a; /* GUS MAX */ else -#endif +#endif /*USE_GUSMAX */ val = 0xff; /*Pre 3.7 - no mixer*/ break; @@ -939,7 +939,7 @@ readgus(uint16_t addr, void *priv) gus->ad_status &= ~0x01; #ifdef OLD_NMI_BEHAVIOR nmi = 0; -#endif +#endif /* OLD_NMI_BEHAVIOR */ fallthrough; case 0x389: val = gus->ad_data; @@ -1182,24 +1182,24 @@ gus_get_buffer(int32_t *buffer, int len, void *priv) { gus_t *gus = (gus_t *) priv; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) ad1848_update(&gus->ad1848); -#endif +#endif /*USE_GUSMAX */ gus_update(gus); for (int c = 0; c < len * 2; c++) { -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) buffer[c] += (int32_t) (gus->ad1848.buffer[c] / 2); -#endif +#endif /*USE_GUSMAX */ buffer[c] += (int32_t) gus->buffer[c & 1][c >> 1]; } -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) gus->ad1848.pos = 0; -#endif +#endif /*USE_GUSMAX */ gus->pos = 0; } @@ -1332,9 +1332,9 @@ gus_reset(void *priv) gus->usrr = 0; -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX gus->max_ctrl = 0; -#endif +#endif /*USE_GUSMAX */ gus->irq_state = 0; gus->midi_irq_state = 0; @@ -1383,7 +1383,7 @@ gus_init(UNUSED(const device_t *info)) io_sethandler(0x0506 + gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if (gus->type == GUS_MAX) { ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231); ad1848_setirq(&gus->ad1848, 5); @@ -1391,7 +1391,7 @@ gus_init(UNUSED(const device_t *info)) io_sethandler(0x10C + gus->base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &gus->ad1848); } -#endif +#endif /*USE_GUSMAX */ timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); @@ -1424,10 +1424,10 @@ gus_speed_changed(void *priv) else gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX if ((gus->type == GUS_MAX) && (gus->max_ctrl)) ad1848_speed_changed(&gus->ad1848); -#endif +#endif /*USE_GUSMAX */ } static const device_config_t gus_config[] = { @@ -1445,12 +1445,12 @@ static const device_config_t gus_config[] = { .description = "Classic", .value = GUS_CLASSIC }, -#if defined(DEV_BRANCH) && defined(USE_GUSMAX) +#ifdef USE_GUSMAX { .description = "MAX", .value = GUS_MAX }, -#endif +#endif /*USE_GUSMAX */ { NULL } }, }, diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index a8c9d3e3ce..21595e3732 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -8,15 +8,13 @@ * * Roland MPU-401 emulation. * - * - * * Authors: DOSBox Team, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2020 DOSBox Team. - * Copyright 2016-2020 Miran Grca. - * Copyright 2016-2020 TheCollector1995. + * Copyright 2008-2024 DOSBox Team. + * Copyright 2016-2024 Miran Grca. + * Copyright 2016-2024 TheCollector1995. */ #include #include @@ -51,10 +49,11 @@ enum { int mpu401_standalone_enable = 0; static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); +static void MPU401_WriteData(mpu_t *mpu, uint8_t val); static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track); static void MPU401_EOIHandler(void *priv); static void MPU401_EOIHandlerDispatch(void *priv); -static void MPU401_NotesOff(mpu_t *mpu, int i); +static __inline void MPU401_NotesOff(mpu_t *mpu, unsigned int i); #ifdef ENABLE_MPU401_LOG int mpu401_do_log = ENABLE_MPU401_LOG; @@ -74,11 +73,26 @@ mpu401_log(const char *fmt, ...) # define mpu401_log(fmt, ...) #endif +static void +MPU401_UpdateIRQ(mpu_t *mpu, int set) +{ + /* Clear IRQ. */ + if ((mpu->irq > 0) && (mpu->irq <= 15)) { + mpu401_log("MPU401_UpdateIRQ(): Int IRQ %i %s.\n", mpu->irq, set ? "set" : "cleared"); + picint_common(1 << mpu->irq, PIC_IRQ_EDGE, set, NULL); + } + + if (mpu->ext_irq_update) { + mpu401_log("MPU401_UpdateIRQ(): Ext IRQ %s.\n", set ? "set" : "cleared"); + mpu->ext_irq_update(mpu->priv, set); + } +} + static void MPU401_ReCalcClock(mpu_t *mpu) { int32_t mintempo = 16; - int32_t maxtempo = 240; + int32_t maxtempo = 240; int32_t freq; if (mpu->clock.timebase < 72) { @@ -96,10 +110,11 @@ MPU401_ReCalcClock(mpu_t *mpu) } mpu->clock.freq = ((uint32_t) (mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; - mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? + mintempo : ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); if (mpu->state.sync_in) { - freq = (int32_t) ((float) (mpu->clock.freq) * mpu->clock.freq_mod); + freq = (int32_t) ((double) (mpu->clock.freq) * mpu->clock.freq_mod); if ((freq > (mpu->clock.timebase * mintempo)) && (freq < (mpu->clock.timebase * maxtempo))) mpu->clock.freq = freq; } @@ -110,135 +125,109 @@ MPU401_ReStartClock(mpu_t *mpu) { if (mpu->clock.active) { timer_disable(&mpu->mpu401_event_callback); - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + timer_set_delay_u64(&mpu->mpu401_event_callback, + (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu401_log("MPU-401: Clock restarted\n"); } } -static void +static __inline void MPU401_StartClock(mpu_t *mpu) { - mpu401_log("MPU401_StartClock(): %i, %i, %i, %i\n", mpu->clock.active, mpu->state.clock_to_host, - mpu->state.playing, (mpu->state.rec == M_RECON)); - if (mpu->clock.active) - return; - if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) - return; - - mpu->clock.active = 1; - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + if (!mpu->clock.active && (mpu->state.playing || + mpu->state.clock_to_host || (mpu->state.rec == M_RECON))) { + mpu->clock.active = 1; + timer_set_delay_u64(&mpu->mpu401_event_callback, + (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu401_log("MPU-401: Clock started\n"); + } } -static void +static __inline void MPU401_StopClock(mpu_t *mpu) { - if (!mpu->state.clock_to_host && !mpu->state.playing && (mpu->state.rec == M_RECOFF)) - return; - mpu->clock.active = 0; - timer_disable(&mpu->mpu401_event_callback); + if (mpu->clock.active && !mpu->state.playing && + !mpu->state.clock_to_host && (mpu->state.rec != M_RECON)) { + mpu->clock.active = 0; + timer_disable(&mpu->mpu401_event_callback); + mpu401_log("MPU-401: Clock stopped\n"); + } } -static void +static __inline void MPU401_RunClock(mpu_t *mpu) { - if (!mpu->clock.active) { + if (mpu->clock.active) + timer_advance_u64(&mpu->mpu401_event_callback, + (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + else timer_disable(&mpu->mpu401_event_callback); - return; - } - timer_advance_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); -#if 0 - mpu401_log("Next event after %" PRIu64 " us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); -#endif } static void -MPU401_QueueByteEx(mpu_t *mpu, uint8_t data, UNUSED(int irq)) +MPU401_QueueByte(mpu_t *mpu, uint8_t data) { if (mpu->state.block_ack) { mpu->state.block_ack = 0; return; } - if (mpu->queue_used == 0) { - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 1); - else { - mpu->state.irq_pending = 1; - picint(1 << mpu->irq); - } + mpu401_log("QueueByte Used=%d.\n", mpu->queue_used); + if (!mpu->queue_used) { + mpu->state.irq_pending = 1; + MPU401_UpdateIRQ(mpu, 1); } if (mpu->queue_used < MPU401_QUEUE) { - int pos = mpu->queue_used + mpu->queue_pos; - + if (mpu->queue_pos > MPU401_QUEUE) fatal("MPU queue overflow\n"); + uint8_t pos = mpu->queue_used + mpu->queue_pos; if (mpu->queue_pos >= MPU401_QUEUE) mpu->queue_pos -= MPU401_QUEUE; if (pos >= MPU401_QUEUE) pos -= MPU401_QUEUE; mpu->queue_used++; + if (pos >= MPU401_QUEUE) fatal("MPU position overflow\n"); mpu->queue[pos] = data; } } static void -MPU401_QueueByte(mpu_t *mpu, uint8_t data) -{ - MPU401_QueueByteEx(mpu, data, 1); -} - -static int -MPU401_IRQPending(mpu_t *mpu) -{ - int irq_pending; - - if (mpu->ext_irq_pending) - irq_pending = mpu->ext_irq_pending(mpu->priv); - else - irq_pending = mpu->state.irq_pending; - - return irq_pending; -} - -static void -MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, UNUSED(int block)) +MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, unsigned int len) { - uint32_t cnt = 0; - int pos; + unsigned int cnt = 0; while (cnt < len) { if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { - pos = mpu->rec_queue_used + mpu->rec_queue_pos; + unsigned int pos = mpu->rec_queue_used + mpu->rec_queue_pos; if (pos >= MPU401_INPUT_QUEUE) pos -= MPU401_INPUT_QUEUE; mpu->rec_queue[pos] = buf[cnt]; mpu->rec_queue_used++; - if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { - /* finish sysex */ + if (!mpu->state.sysex_in_finished && (buf[cnt] == MSG_EOX)) { + /* Finish SysEx */ mpu->state.sysex_in_finished = 1; break; } cnt++; } } - - if (mpu->queue_used == 0) { - if (mpu->state.rec_copy || MPU401_IRQPending(mpu)) { - if (MPU401_IRQPending(mpu)) { - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); - } + if (!mpu->queue_used) { + if (mpu->state.rec_copy || mpu->state.irq_pending) { + if (mpu->state.irq_pending) { + mpu->state.irq_pending = 0; + MPU401_UpdateIRQ(mpu, 0); } return; } + mpu->state.rec_copy = 1; if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; + MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); - mpu->rec_queue_used--; - mpu->rec_queue_pos++; + mpu->rec_queue_used--; + mpu->rec_queue_pos++; } } @@ -250,12 +239,8 @@ MPU401_ClrQueue(mpu_t *mpu) mpu->rec_queue_used = 0; mpu->rec_queue_pos = 0; mpu->state.sysex_in_finished = 1; - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); - } + mpu->state.irq_pending = 0; + MPU401_UpdateIRQ(mpu, 0); } static void @@ -263,86 +248,85 @@ MPU401_Reset(mpu_t *mpu) { uint8_t i; -#ifdef DOSBOX_CODE - if (mpu->mode == M_INTELLIGENT) { - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); - } - } -#else - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); + midi_reset(); + /* Clear MIDI buffers, terminate notes. */ + midi_clear_buffer(); + for (i = 0xb0; i <= 0xbf; i++) { + midi_raw_out_byte(i); + midi_raw_out_byte(0x7b); + midi_raw_out_byte(0); } -#endif - mpu->mode = M_INTELLIGENT; - mpu->midi_thru = 0; - mpu->state.rec = M_RECOFF; - mpu->state.eoi_scheduled = 0; - mpu->state.wsd = 0; - mpu->state.wsm = 0; - mpu->state.conductor = 0; - mpu->state.cond_req = 0; - mpu->state.cond_set = 0; - mpu->state.playing = 0; - mpu->state.run_irq = 0; - mpu->state.cmask = 0xff; - mpu->state.amask = mpu->state.tmask = 0; - mpu->state.midi_mask = 0xffff; - mpu->state.command_byte = 0; - mpu->state.block_ack = 0; - mpu->clock.tempo = mpu->clock.old_tempo = 100; - mpu->clock.timebase = mpu->clock.old_timebase = 120; + mpu->state.irq_pending = 0; + MPU401_UpdateIRQ(mpu, 0); + + timer_disable(&mpu->mpu401_event_callback); + + mpu->mode = M_INTELLIGENT; + mpu->midi_thru = 0; + mpu->state.rec = M_RECOFF; + mpu->state.eoi_scheduled = 0; + mpu->state.wsd = 0; + mpu->state.wsm = 0; + mpu->state.conductor = 0; + mpu->state.cond_req = 0; + mpu->state.cond_set = 0; + mpu->state.playing = 0; + mpu->state.run_irq = 0; + mpu->state.cmask = 0xff; + mpu->state.amask = mpu->state.tmask = 0; + mpu->state.midi_mask = 0xffff; + mpu->state.command_byte = 0; + mpu->state.block_ack = 0; + mpu->clock.tempo = mpu->clock.old_tempo = 100; + mpu->clock.timebase = mpu->clock.old_timebase = 120; mpu->clock.tempo_rel = mpu->clock.old_tempo_rel = 0x40; mpu->clock.freq_mod = 1.0; mpu->clock.tempo_grad = 0; + mpu->state.clock_to_host = 0; MPU401_StopClock(mpu); MPU401_ReCalcClock(mpu); for (i = 0; i < 4; i++) - mpu->clock.cth_rate[i] = 60; - - mpu->clock.cth_counter = 0; - mpu->clock.midimetro = 12; - mpu->clock.metromeas = 8; - mpu->filter.rec_measure_end = 1; - mpu->filter.rt_out = 1; - mpu->filter.rt_affection = 1; - mpu->filter.allnotesoff_out = 1; - mpu->filter.all_thru = 1; - mpu->filter.midi_thru = 1; - mpu->filter.commonmsgs_thru = 1; + mpu->clock.cth_rate[i] = 60; + + mpu->clock.cth_counter = 0; + mpu->clock.midimetro = 12; + mpu->clock.metromeas = 8; + mpu->filter.rec_measure_end = 1; + mpu->filter.rt_out = 1; + mpu->filter.rt_affection = 1; + mpu->filter.allnotesoff_out = 1; + mpu->filter.all_thru = 1; + mpu->filter.midi_thru = 1; + mpu->filter.commonmsgs_thru = 1; /* Reset channel reference and input tables. */ for (i = 0; i < 4; i++) { - mpu->chanref[i].on = 1; - mpu->chanref[i].chan = i; - mpu->ch_toref[i] = i; + mpu->chanref[i].on = 1; + mpu->chanref[i].chan = i; + + mpu->ch_toref[i] = i; } for (i = 0; i < 16; i++) { - mpu->inputref[i].on = 1; - mpu->inputref[i].chan = i; + mpu->inputref[i].on = 1; + mpu->inputref[i].chan = i; if (i > 3) - mpu->ch_toref[i] = 4; /* Dummy reftable. */ + mpu->ch_toref[i] = 4; /* Dummy reftable. */ } MPU401_ClrQueue(mpu); - mpu->state.data_onoff = -1; + mpu->state.data_onoff = -1; + + mpu->state.req_mask = 0; + mpu->condbuf.counter = 0; - mpu->state.req_mask = 0; - mpu->condbuf.counter = 0; - mpu->condbuf.type = T_OVERFLOW; + mpu->condbuf.type = T_OVERFLOW; for (i = 0; i < 8; i++) { - mpu->playbuf[i].type = T_OVERFLOW; - mpu->playbuf[i].counter = 0; + mpu->playbuf[i].type = T_OVERFLOW; + mpu->playbuf[i].counter = 0; } /* Clear MIDI buffers, terminate notes. */ @@ -355,15 +339,26 @@ MPU401_Reset(mpu_t *mpu) } } +static uint8_t +MPU401_ReadStatus(mpu_t *mpu) +{ + uint8_t ret = 0x00; + + if (mpu->state.cmd_pending) + ret = STATUS_OUTPUT_NOT_READY; + if (!mpu->queue_used) + ret = STATUS_INPUT_NOT_READY; + + ret |= 0x3f; + + return ret; +} + static void MPU401_ResetDone(void *priv) { mpu_t *mpu = (mpu_t *) priv; - mpu401_log("MPU-401 reset callback\n"); - - timer_disable(&mpu->mpu401_reset_callback); - mpu->state.reset = 0; if (mpu->state.cmd_pending) { @@ -425,15 +420,15 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) } switch (val & 0xc) { /* Playing */ case 0x4: /* Stop */ - MPU401_StopClock(mpu); mpu->state.playing = 0; + MPU401_StopClock(mpu); for (i = 0; i < 16; i++) MPU401_NotesOff(mpu, i); mpu->filter.prchg_mask = 0; break; case 0x8: /* Start */ - MPU401_StartClock(mpu); mpu->state.playing = 1; + MPU401_StartClock(mpu); MPU401_ClrQueue(mpu); break; @@ -444,14 +439,14 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) case 0: /* check if it waited for MIDI RT command */ if (((val & 3) < 2) || !mpu->filter.rt_affection || (mpu->state.rec != M_RECSTB)) break; - MPU401_StartClock(mpu); mpu->state.rec = M_RECON; + MPU401_StartClock(mpu); if (mpu->filter.prchg_mask) send_prchg = 1; break; case 0x10: /* Stop */ - MPU401_StopClock(mpu); mpu->state.rec = M_RECOFF; + MPU401_StopClock(mpu); MPU401_QueueByte(mpu, MSG_MPU_ACK); MPU401_QueueByte(mpu, mpu->clock.rec_counter); MPU401_QueueByte(mpu, MSG_MPU_END); @@ -480,7 +475,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) /* record counter hack: needed by Prism, but sent only on cmd 0x20/0x26 (or breaks Ballade) */ uint8_t rec_cnt = mpu->clock.rec_counter; if (((val == 0x20) || (val == 0x26)) && (mpu->state.rec == M_RECON)) - MPU401_RecQueueBuffer(mpu, &rec_cnt, 1, 0); + MPU401_RecQueueBuffer(mpu, &rec_cnt, 1); if (send_prchg) { for (i = 0; i < 16; i++) { @@ -488,11 +483,12 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) recmsg[0] = mpu->clock.rec_counter; recmsg[1] = 0xc0 | i; recmsg[2] = mpu->filter.prchg_buf[i]; - MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); + MPU401_RecQueueBuffer(mpu, recmsg, 3); mpu->filter.prchg_mask &= ~(1 << i); } } } + return; } else if ((val >= 0xa0) && (val <= 0xa7)) /* Request play counter */ MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ @@ -552,7 +548,8 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) return; case 0x80: /* Internal clock */ if (mpu->clock.active && mpu->state.sync_in) { - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + timer_set_delay_u64(&mpu->mpu401_event_callback, + (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); mpu->clock.freq_mod = 1.0; } mpu->state.sync_in = 0; @@ -594,12 +591,12 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.rt_affection = !!(val & 1); break; case 0x94: /* Clock to host */ - MPU401_StopClock(mpu); mpu->state.clock_to_host = 0; + MPU401_StopClock(mpu); break; case 0x95: - MPU401_StartClock(mpu); mpu->state.clock_to_host = 1; + MPU401_StartClock(mpu); break; case 0x96: case 0x97: /* Sysex input allow */ @@ -650,6 +647,8 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->state.conductor = mpu->state.cond_set; mpu->clock.cth_counter = mpu->clock.cth_old = 0; mpu->clock.measure_counter = mpu->clock.meas_old = 0; + mpu->state.req_mask = 0; + mpu->state.irq_pending = 1; break; case 0xb9: /* Clear play map */ for (i = 0; i < 16; i++) @@ -661,6 +660,8 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->state.last_rtcmd = 0; mpu->clock.cth_counter = mpu->clock.cth_old = 0; mpu->clock.measure_counter = mpu->clock.meas_old = 0; + mpu->state.req_mask = 0; + mpu->state.irq_pending = 1; break; case 0xba: /* Clear record counter */ mpu->clock.rec_counter = 0; @@ -704,38 +705,106 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) return; break; - default: + default: #if 0 - mpu401_log("MPU-401:Unhandled command %X",val); + mpu401_log("MPU-401:Unhandled command %X",val); #endif - break; + break; } MPU401_QueueByte(mpu, MSG_MPU_ACK); } -static void -MPU401_WriteData(mpu_t *mpu, uint8_t val) +void +MPU401_ReadRaiseIRQ(mpu_t *mpu) { - static int length; - static int cnt; + /* Clear IRQ. */ + MPU401_UpdateIRQ(mpu, 0); -#ifdef DOSBOX_CODE - if (mpu->mode == M_UART) { - midi_raw_out_byte(val); - return; + if (mpu->queue_used) + MPU401_UpdateIRQ(mpu, 1); +} + +uint8_t +MPU401_ReadData(mpu_t *mpu) +{ + uint8_t ret = MSG_MPU_ACK; + + if (mpu->queue_used) { + mpu->queue_pos -= (mpu->queue_pos >= MPU401_QUEUE) ? MPU401_QUEUE : 0; + ret = mpu->queue[mpu->queue_pos]; + mpu->queue_pos++; + mpu->queue_used--; } - if (!mpu->intelligent) { - mpu->state.command_byte = 0; - return; + /* Shouldn't this check mpu->mode? */ + if (!mpu->intelligent || (mpu->mode == M_UART)) { + MPU401_ReadRaiseIRQ(mpu); + return ret; } -#else + + mpu401_log("QueueUsed=%d.\n", mpu->queue_used); + if (!mpu->queue_used) + MPU401_UpdateIRQ(mpu, 0); + + if (mpu->state.rec_copy && !mpu->rec_queue_used) { + MPU401_ReadRaiseIRQ(mpu); + mpu->state.rec_copy = 0; + MPU401_EOIHandler(mpu); + return ret; + } + + /* Copy from recording buffer. */ + if (!mpu->queue_used && mpu->rec_queue_used) { + mpu->state.rec_copy = 1; + if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) + mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; + + MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); + mpu->rec_queue_pos++; + mpu->rec_queue_used--; + } + + MPU401_ReadRaiseIRQ(mpu); + + if ((ret >= 0xf0) && (ret <= 0xf7)) { /* MIDI data request */ + mpu->state.track = ret & 7; + mpu->state.data_onoff = 0; + mpu->state.cond_req = 0; + mpu->state.track_req = 1; + } + + if (ret == MSG_MPU_COMMAND_REQ) { + mpu->state.data_onoff = 0; + mpu->state.cond_req = 1; + if (mpu->condbuf.type != T_OVERFLOW) { + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); + if (mpu->state.command_byte) + MPU401_WriteData(mpu, mpu->condbuf.value[1]); + mpu->condbuf.type = T_OVERFLOW; + } + } + + if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) + MPU401_EOIHandlerDispatch(mpu); + + return ret; +} + +static void +MPU401_WriteData(mpu_t *mpu, uint8_t val) +{ + static unsigned int length; + static unsigned int cnt; + static unsigned int posd; + if (!mpu->intelligent || (mpu->mode == M_UART)) { midi_raw_out_byte(val); + if (val == 0xff) + midi_reset(); return; } -#endif switch (mpu->state.command_byte) { /* 0xe# command data */ case 0x00: @@ -759,6 +828,7 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) MPU401_ReStartClock(mpu); return; case 0xe2: /* Set gradation for relative tempo */ + mpu->state.command_byte = 0; mpu->clock.tempo_grad = val; MPU401_ReCalcClock(mpu); MPU401_ReStartClock(mpu); @@ -844,6 +914,7 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) } if (cnt == length) { + mpu->playbuf[mpu->state.track].vlength = cnt; MPU401_IntelligentOut(mpu, mpu->state.track); mpu->state.wsd = 0; mpu->state.track = mpu->state.old_track; @@ -874,8 +945,9 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) break; default: + length = 0; mpu->state.wsm = 0; - return; + break; } } else if (val & 0x80) { midi_raw_out_byte(MSG_EOX); @@ -900,38 +972,36 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) case -1: return; case 0: /* Timing byte */ - mpu->condbuf.length = 0; + mpu->condbuf.vlength = 0; if (val < 0xf0) mpu->state.data_onoff++; else { - mpu->state.cond_req = 0; mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); - break; + return; } - mpu->state.send_now = !val ? 1 : 0; + /* A timing value of 0 means send it now! */ + mpu->state.send_now = (val == 0); mpu->condbuf.counter = val; break; case 1: /* Command byte #1 */ mpu->condbuf.type = T_COMMAND; if ((val == 0xf8) || (val == 0xf9) || (val == 0xfc)) mpu->condbuf.type = T_OVERFLOW; - mpu->condbuf.value[mpu->condbuf.length] = val; - mpu->condbuf.length++; - if ((val & 0xf0) != 0xe0) { /*no cmd data byte*/ - MPU401_EOIHandler(mpu); - mpu->state.data_onoff = -1; - mpu->state.cond_req = 0; - } else + + mpu->condbuf.value[mpu->condbuf.vlength] = val; + mpu->condbuf.vlength++; + + if ((val & 0xf0) != 0xe0) + MPU401_EOIHandlerDispatch(mpu); + else mpu->state.data_onoff++; break; case 2: /* Command byte #2 */ - mpu->condbuf.value[mpu->condbuf.length] = val; - mpu->condbuf.length++; - MPU401_EOIHandler(mpu); - mpu->state.data_onoff = -1; - mpu->state.cond_req = 0; + mpu->condbuf.value[mpu->condbuf.vlength] = val; + mpu->condbuf.vlength++; + MPU401_EOIHandlerDispatch(mpu); break; default: @@ -939,103 +1009,95 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) } return; } - switch (mpu->state.data_onoff) { /* Data */ case -1: - break; + return; case 0: /* Timing byte */ if (val < 0xf0) - mpu->state.data_onoff++; + mpu->state.data_onoff = 1; else { mpu->state.data_onoff = -1; MPU401_EOIHandlerDispatch(mpu); mpu->state.track_req = 0; return; } - mpu->state.send_now = !val ? 1 : 0; + mpu->state.send_now = (val == 0); mpu->playbuf[mpu->state.track].counter = val; break; case 1: /* MIDI */ - cnt = 0; - mpu->state.data_onoff++; - switch (val & 0xf0) { - case 0xc0: - case 0xd0: /* MIDI Message */ - length = mpu->playbuf[mpu->state.track].length = 2; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - case 0xe0: - length = mpu->playbuf[mpu->state.track].length = 3; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - case 0xf0: /* System message or mark */ - mpu->playbuf[mpu->state.track].sys_val = val; - if (val > 0xf7) { - mpu->playbuf[mpu->state.track].type = T_MARK; - if (val == 0xf9) - mpu->clock.measure_counter = 0; - } else { -#if 0 - mpu401_log("MPU-401:Illegal message"); -#endif - mpu->playbuf[mpu->state.track].type = T_OVERFLOW; - } - mpu->state.data_onoff = -1; - MPU401_EOIHandler(mpu); - mpu->state.track_req = 0; - return; - default: /* MIDI with running status */ - cnt++; - length = mpu->playbuf[mpu->state.track].length; - mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; - break; - } - break; - case 2: - if (cnt < length) { - mpu->playbuf[mpu->state.track].value[cnt] = val; - cnt++; - } - if (cnt == length) { - mpu->state.data_onoff = -1; - mpu->state.track_req = 0; - MPU401_EOIHandler(mpu); + mpu->playbuf[mpu->state.track].vlength++; + posd = mpu->playbuf[mpu->state.track].vlength; + + if (posd == 1) { + switch (val & 0xf0) { + case 0xc0: + case 0xd0: /* MIDI Message */ + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + length = mpu->playbuf[mpu->state.track].length = 2; + break; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + case 0xe0: + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + length = mpu->playbuf[mpu->state.track].length = 3; + break; + case 0xf0: /* System message or mark */ + mpu->playbuf[mpu->state.track].sys_val = val; + if (val > 0xf7) { + mpu->playbuf[mpu->state.track].type = T_MARK; + if (val == 0xf9) + mpu->clock.measure_counter = 0; + } else + mpu->playbuf[mpu->state.track].type = T_OVERFLOW; + + length = 1; + break; + + default: /* MIDI with running status */ + posd++; + length = mpu->playbuf[mpu->state.track].length; + mpu->playbuf[mpu->state.track].vlength++; + mpu->playbuf[mpu->state.track].type = T_MIDI_NORM; + break; + } } - break; - default: + if (!((posd == 1) && (val >= 0xf0))) + mpu->playbuf[mpu->state.track].value[posd - 1] = val; + + if (posd == length) { + MPU401_EOIHandlerDispatch(mpu); + mpu->state.track_req = 0; + } break; } - - return; } static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) { - uint8_t chan; - uint8_t chrefnum; - uint8_t key; - uint8_t msg; - int send; - int retrigger; + unsigned int chan; + unsigned int chrefnum; + uint8_t key; + uint8_t msg; + uint8_t val; + int send; + int retrigger; switch (mpu->playbuf[track].type) { case T_OVERFLOW: break; - case T_MARK: - if (mpu->playbuf[track].sys_val == 0xfc) { - midi_raw_out_rt_byte(mpu->playbuf[track].sys_val); + val = mpu->playbuf[track].sys_val; + if (val == 0xfc) { + midi_raw_out_rt_byte(val); mpu->state.amask &= ~(1 << track); + mpu->state.req_mask &= ~(1 << track); } break; - case T_MIDI_NORM: chan = mpu->playbuf[track].value[0] & 0xf; key = mpu->playbuf[track].value[1] & 0x7f; @@ -1043,18 +1105,20 @@ MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) send = 1; retrigger = 0; switch (msg = mpu->playbuf[track].value[0] & 0xf0) { - case 0x80: /* note off */ + case 0x80: /* Note off */ if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) send = 0; if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) send = 0; + mpu->chanref[chrefnum].M_DELKEY; break; - case 0x90: /* note on */ + case 0x90: /* Note on */ if (mpu->inputref[chan].on && (mpu->inputref[chan].M_GETKEY)) retrigger = 1; if (mpu->chanref[chrefnum].on && (!(mpu->chanref[chrefnum].M_GETKEY))) retrigger = 1; + mpu->chanref[chrefnum].M_SETKEY; break; case 0xb0: @@ -1063,7 +1127,6 @@ MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) return; } break; - default: break; } @@ -1073,7 +1136,7 @@ MPU401_IntelligentOut(mpu_t *mpu, uint8_t track) midi_raw_out_byte(0); } if (send) { - for (uint8_t i = 0; i < mpu->playbuf[track].length; i++) + for (uint8_t i = 0; i < mpu->playbuf[track].vlength; ++i) midi_raw_out_byte(mpu->playbuf[track].value[i]); } break; @@ -1087,8 +1150,8 @@ static void UpdateTrack(mpu_t *mpu, uint8_t track) { MPU401_IntelligentOut(mpu, track); - if (mpu->state.amask & (1 << track)) { + mpu->playbuf[track].vlength = 0; mpu->playbuf[track].type = T_OVERFLOW; mpu->playbuf[track].counter = 0xf0; mpu->state.req_mask |= (1 << track); @@ -1098,39 +1161,120 @@ UpdateTrack(mpu_t *mpu, uint8_t track) } } +static void +MPU401_Event(void *priv) +{ + mpu_t *mpu = (mpu_t *) priv; + + if (!mpu->intelligent || (mpu->mode == M_UART)) + return; + + if (mpu->state.irq_pending) + goto next_event; + + if (mpu->state.playing) { + /* Decrease counters. */ + for (uint8_t i = 0; i < 8; i++) { + if (mpu->state.amask & (1 << i)) { + if (mpu->playbuf[i].counter) + mpu->playbuf[i].counter--; + if (!mpu->playbuf[i].counter) + UpdateTrack(mpu, i); + } + } + if (mpu->state.conductor) { + if (mpu->condbuf.counter) + mpu->condbuf.counter--; + if (!mpu->condbuf.counter) { + mpu->condbuf.vlength = 0; + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } + } + } + + if (mpu->state.clock_to_host) { + mpu->clock.cth_counter++; + if (mpu->clock.cth_counter >= mpu->clock.cth_rate[mpu->clock.cth_mode]) { + mpu->clock.cth_counter = 0; + ++mpu->clock.cth_mode; + mpu->clock.cth_mode %= 4; + mpu->state.req_mask |= (1 << 13); + } + } + + /* Recording */ + if (mpu->state.rec == M_RECON) { + mpu->clock.rec_counter++; + if (mpu->clock.rec_counter >= 240) { + mpu->clock.rec_counter = 0; + mpu->state.req_mask |= (1 << 8); + } + } + + if (mpu->state.playing || (mpu->state.rec == M_RECON)) { + int max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; + if (max_meascnt != 0) { /* Measure end */ + if (++mpu->clock.measure_counter >= max_meascnt) { + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xf8); + + mpu->clock.measure_counter=0; + if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) + mpu->state.req_mask |= (1 << 12); + } + } + } + + if (!mpu->state.irq_pending && mpu->state.req_mask) + MPU401_EOIHandler(mpu); + +next_event: + MPU401_RunClock(mpu); + if (mpu->state.sync_in) + mpu->clock.ticks_in++; +} + +static void +MPU401_EOIHandlerDispatch(void *priv) +{ + mpu_t *mpu = (mpu_t *) priv; + + mpu401_log("EOI handler dispatch\n"); + if (mpu->state.send_now) { + mpu->state.eoi_scheduled = 1; + timer_set_delay_u64(&mpu->mpu401_eoi_callback, 60LL * TIMER_USEC); /* Possibly a bit longer */ + } else if (!mpu->state.eoi_scheduled) + MPU401_EOIHandler(mpu); +} + /* Updates counters and requests new data on "End of Input" */ static void MPU401_EOIHandler(void *priv) { mpu_t *mpu = (mpu_t *) priv; - uint8_t i; mpu401_log("MPU-401 end of input callback\n"); - timer_disable(&mpu->mpu401_eoi_callback); mpu->state.eoi_scheduled = 0; if (mpu->state.send_now) { mpu->state.send_now = 0; if (mpu->state.cond_req) { + mpu->condbuf.vlength = 0; mpu->condbuf.counter = 0xf0; mpu->state.req_mask |= (1 << 9); } else UpdateTrack(mpu, mpu->state.track); } - if (mpu->state.rec_copy || !mpu->state.sysex_in_finished) return; + mpu->state.irq_pending = 0; + if (!mpu->state.req_mask || !mpu->clock.active) return; - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - } - - i = 0; + uint8_t i = 0; do { if (mpu->state.req_mask & (1 << i)) { MPU401_QueueByte(mpu, 0xf0 + i); @@ -1140,17 +1284,29 @@ MPU401_EOIHandler(void *priv) } while ((i++) < 16); } -static void -MPU401_EOIHandlerDispatch(void *priv) +static __inline void +MPU401_NotesOff(mpu_t *mpu, unsigned int i) { - mpu_t *mpu = (mpu_t *) priv; + if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && + (mpu->inputref[i].key[0] | mpu->inputref[i].key[1] | + mpu->inputref[i].key[2] | mpu->inputref[i].key[3]))) { + for (uint8_t j = 0;j < 4; j++) + mpu->chanref[mpu->ch_toref[i]].key[j] = 0; - mpu401_log("EOI handler dispatch\n"); - if (mpu->state.send_now) { - mpu->state.eoi_scheduled = 1; - timer_advance_u64(&mpu->mpu401_eoi_callback, 60LL * TIMER_USEC); /* Possibly a bit longer */ - } else if (!mpu->state.eoi_scheduled) - MPU401_EOIHandler(mpu); + midi_raw_out_byte(0xb0 | i); + midi_raw_out_byte(123); + midi_raw_out_byte(0); + } else if (mpu->chanref[mpu->ch_toref[i]].on) { + for (uint8_t key = 0; key < 128; key++) { + if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && + !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { + midi_raw_out_byte(0x80 | i); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } + mpu->chanref[mpu->ch_toref[i]].M_DELKEY; + } + } } static void @@ -1159,100 +1315,6 @@ imf_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), UNUSED(void *priv)) mpu401_log("IMF:Wr %4X,%X\n", addr, val); } -void -MPU401_ReadRaiseIRQ(mpu_t *mpu) -{ - /* Clear IRQ. */ - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 0); - else { - mpu->state.irq_pending = 0; - picintc(1 << mpu->irq); - } - - if (mpu->queue_used) { - /* Bytes remaining in queue, raise IRQ again. */ - if (mpu->ext_irq_update) - mpu->ext_irq_update(mpu->priv, 1); - else { - mpu->state.irq_pending = 1; - picint(1 << mpu->irq); - } - } -} - -uint8_t -MPU401_ReadData(mpu_t *mpu) -{ - uint8_t ret; - - ret = MSG_MPU_ACK; - - if (mpu->queue_used) { - if (mpu->queue_pos >= MPU401_QUEUE) - mpu->queue_pos -= MPU401_QUEUE; - ret = mpu->queue[mpu->queue_pos]; - mpu->queue_pos++; - mpu->queue_used--; - } - - /* Shouldn't this check mpu->mode? */ -#ifdef DOSBOX_CODE - if (mpu->mode == M_UART) { - MPU401_ReadRaiseIRQ(mpu); - return ret; - } -#else - if (!mpu->intelligent || (mpu->mode == M_UART)) { - MPU401_ReadRaiseIRQ(mpu); - return ret; - } -#endif - - if (mpu->state.rec_copy && !mpu->rec_queue_used) { - mpu->state.rec_copy = 0; - MPU401_EOIHandler(mpu); - return ret; - } - - /* Copy from recording buffer. */ - if (!mpu->queue_used && mpu->rec_queue_used) { - mpu->state.rec_copy = 1; - if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) - mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; - MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); - mpu->rec_queue_pos++; - mpu->rec_queue_used--; - } - - MPU401_ReadRaiseIRQ(mpu); - - if ((ret >= 0xf0) && (ret <= 0xf7)) { - /* MIDI data request */ - mpu->state.track = ret & 7; - mpu->state.data_onoff = 0; - mpu->state.cond_req = 0; - mpu->state.track_req = 1; - } - - if (ret == MSG_MPU_COMMAND_REQ) { - mpu->state.data_onoff = 0; - mpu->state.cond_req = 1; - if (mpu->condbuf.type != T_OVERFLOW) { - mpu->state.block_ack = 1; - MPU401_WriteCommand(mpu, mpu->condbuf.value[0]); - if (mpu->state.command_byte) - MPU401_WriteData(mpu, mpu->condbuf.value[1]); - mpu->condbuf.type = T_OVERFLOW; - } - } - - if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) - MPU401_EOIHandlerDispatch(mpu); - - return ret; -} - void mpu401_write(uint16_t addr, uint8_t val, void *priv) { @@ -1288,12 +1350,7 @@ mpu401_read(uint16_t addr, void *priv) break; case 1: /* Read Status */ - if (mpu->state.cmd_pending) - ret = STATUS_OUTPUT_NOT_READY; - if (!mpu->queue_used) - ret = STATUS_INPUT_NOT_READY; - ret |= 0x3f; - + ret = MPU401_ReadStatus(mpu); mpu401_log("Read Status (0x331) %x\n", ret); break; @@ -1305,111 +1362,6 @@ mpu401_read(uint16_t addr, void *priv) return ret; } -static void -MPU401_Event(void *priv) -{ - mpu_t *mpu = (mpu_t *) priv; - int max_meascnt; - - mpu401_log("MPU-401 event callback\n"); - -#ifdef DOSBOX_CODE - if (mpu->mode == M_UART) { - timer_disable(&mpu->mpu401_event_callback); - return; - } -#else - if (!mpu->intelligent || (mpu->mode == M_UART)) { - timer_disable(&mpu->mpu401_event_callback); - return; - } -#endif - - if (MPU401_IRQPending(mpu)) - goto next_event; - - if (mpu->state.playing) { - for (uint8_t i = 0; i < 8; i++) { - /* Decrease counters. */ - if (mpu->state.amask & (1 << i)) { - mpu->playbuf[i].counter--; - if (mpu->playbuf[i].counter <= 0) - UpdateTrack(mpu, i); - } - } - - if (mpu->state.conductor) { - mpu->condbuf.counter--; - if (mpu->condbuf.counter <= 0) { - mpu->condbuf.counter = 0xf0; - mpu->state.req_mask |= (1 << 9); - } - } - } - - if (mpu->state.clock_to_host) { - mpu->clock.cth_counter++; - if (mpu->clock.cth_counter >= mpu->clock.cth_rate[mpu->clock.cth_mode]) { - mpu->clock.cth_counter = 0; - mpu->clock.cth_mode++; - mpu->clock.cth_mode %= 4; - mpu->state.req_mask |= (1 << 13); - } - } - - if (mpu->state.rec == M_RECON) { - /* Recording. */ - mpu->clock.rec_counter++; - if (mpu->clock.rec_counter >= 240) { - mpu->clock.rec_counter = 0; - mpu->state.req_mask |= (1 << 8); - } - } - - if (mpu->state.playing || (mpu->state.rec == M_RECON)) { - max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; - if (max_meascnt != 0) { - /* Measure end. */ - if (++mpu->clock.measure_counter >= max_meascnt) { - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xf8); - mpu->clock.measure_counter = 0; - if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) - mpu->state.req_mask |= (1 << 12); - } - } - } - - if (!MPU401_IRQPending(mpu) && mpu->state.req_mask) - MPU401_EOIHandler(mpu); - -next_event: - MPU401_RunClock(mpu); - if (mpu->state.sync_in) - mpu->clock.ticks_in++; -} - -static void -MPU401_NotesOff(mpu_t *mpu, int i) -{ - if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && (mpu->inputref[i].key[0] | mpu->inputref[i].key[1] | mpu->inputref[i].key[2] | mpu->inputref[i].key[3]))) { - for (uint8_t j = 0; j < 4; j++) - mpu->chanref[mpu->ch_toref[i]].key[j] = 0; - midi_raw_out_byte(0xb0 | i); - midi_raw_out_byte(123); - midi_raw_out_byte(0); - } else if (mpu->chanref[mpu->ch_toref[i]].on) { - for (uint8_t key = 0; key < 128; key++) { - if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { - midi_raw_out_byte(0x80 | i); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } - mpu->chanref[mpu->ch_toref[i]].M_DELKEY; - } - } -} - /*Input handler for SysEx */ int MPU401_InputSysex(void *priv, uint8_t *buffer, uint32_t len, int abort) @@ -1420,14 +1372,12 @@ MPU401_InputSysex(void *priv, uint8_t *buffer, uint32_t len, int abort) mpu401_log("MPU401 Input Sysex\n"); -#ifdef DOSBOX_CODE - if (mpu->mode == M_UART) { -#else if (!mpu->intelligent || mpu->mode == M_UART) { -#endif /* UART mode input. */ for (i = 0; i < len; i++) MPU401_QueueByte(mpu, buffer[i]); + + MPU401_ReadRaiseIRQ(mpu); return 0; } @@ -1440,7 +1390,7 @@ MPU401_InputSysex(void *priv, uint8_t *buffer, uint32_t len, int abort) if (mpu->state.sysex_in_finished) { if (mpu->rec_queue_used >= MPU401_INPUT_QUEUE) return len; - MPU401_RecQueueBuffer(mpu, &val_ff, 1, 1); + MPU401_RecQueueBuffer(mpu, &val_ff, 1); mpu->state.sysex_in_finished = 0; mpu->clock.rec_counter = 0; } @@ -1449,10 +1399,10 @@ MPU401_InputSysex(void *priv, uint8_t *buffer, uint32_t len, int abort) int available = MPU401_INPUT_QUEUE - mpu->rec_queue_used; if (available >= len) { - MPU401_RecQueueBuffer(mpu, buffer, len, 1); + MPU401_RecQueueBuffer(mpu, buffer, len); return 0; } else { - MPU401_RecQueueBuffer(mpu, buffer, available, 1); + MPU401_RecQueueBuffer(mpu, buffer, available); if (mpu->state.sysex_in_finished) return 0; return (len - available); @@ -1490,11 +1440,7 @@ MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) mpu401_log("MPU401 Input Msg\n"); -#ifdef DOSBOX_CODE - if (mpu->mode == M_INTELLIGENT) { -#else if (mpu->intelligent && (mpu->mode == M_INTELLIGENT)) { -#endif if (msg[0] < 0x80) { /* Expand running status */ msg[2] = msg[1]; @@ -1606,7 +1552,7 @@ MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) if (!(mpu->filter.rt_in && (msg[0] <= 0xfc) && (msg[0] >= 0xfa))) { recdata[0] = 0xff; recdata[1] = msg[0]; - MPU401_RecQueueBuffer(mpu, recdata, 2, 1); + MPU401_RecQueueBuffer(mpu, recdata, 2); send = 0; } } else { /* Common or system. */ @@ -1624,7 +1570,7 @@ MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) recmsg[1] = msg[0]; recmsg[2] = msg[1]; recmsg[3] = msg[2]; - MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + MPU401_RecQueueBuffer(mpu, recmsg, len + 1); } if (mpu->filter.rt_affection) { switch (msg[0]) { @@ -1678,7 +1624,7 @@ MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) recmsg[1] = msg[0]; recmsg[2] = msg[1]; recmsg[3] = msg[2]; - MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + MPU401_RecQueueBuffer(mpu, recmsg, len + 1); mpu->clock.rec_counter = 0; } else if (mpu->filter.data_in_stop) { if (mpu->filter.timing_in_stop) { @@ -1686,13 +1632,13 @@ MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) recmsg[1] = msg[0]; recmsg[2] = msg[1]; recmsg[3] = msg[2]; - MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + MPU401_RecQueueBuffer(mpu, recmsg, len + 1); } else { recmsg[0] = msg[0]; recmsg[1] = msg[1]; recmsg[2] = msg[2]; recmsg[3] = 0; - MPU401_RecQueueBuffer(mpu, recmsg, len, 1); + MPU401_RecQueueBuffer(mpu, recmsg, len); } } } @@ -1702,6 +1648,8 @@ MPU401_InputMsg(void *priv, uint8_t *msg, uint32_t len) /* UART mode input. */ for (i = 0; i < len; i++) MPU401_QueueByte(mpu, msg[i]); + + MPU401_ReadRaiseIRQ(mpu); } void @@ -1823,8 +1771,7 @@ mpu401_standalone_init(const device_t *info) int irq; uint16_t base; - mpu = malloc(sizeof(mpu_t)); - memset(mpu, 0, sizeof(mpu_t)); + mpu = calloc(1, sizeof(mpu_t)); mpu401_log("mpu_init\n"); diff --git a/src/sound/snd_opl_nuked.c b/src/sound/snd_opl_nuked.c index 95b61638eb..f1132867b2 100644 --- a/src/sound/snd_opl_nuked.c +++ b/src/sound/snd_opl_nuked.c @@ -18,7 +18,7 @@ * siliconpr0n.org(John McMaster, digshadow): * YMF262 and VRC VII decaps and die shots. * - * Version: 1.8.0 + * Version: 1.8 * * Translation from C++ into C done by Miran Grca. * @@ -35,7 +35,7 @@ * * Copyright 2017-2020 Fred N. van Kempen. * Copyright 2016-2020 Miran Grca. - * Copyright 2013-2018 Alexey Khokholov (Nuke.YKT) + * Copyright 2013-2020 Alexey Khokholov (Nuke.YKT) */ #include #include @@ -45,14 +45,27 @@ #define HAVE_STDARG_H #include <86box/86box.h> -#include <86box/snd_opl_nuked.h> #include <86box/sound.h> #include <86box/timer.h> #include <86box/device.h> #include <86box/snd_opl.h> +#include <86box/snd_opl_nuked.h> + + +#if OPL_ENABLE_STEREOEXT && !defined OPL_SIN +#ifndef _USE_MATH_DEFINES +#define _USE_MATH_DEFINES 1 +#endif +#include +// input: [0, 256), output: [0, 65536] +#define OPL_SIN(x) ((int32_t)(sin((x) * M_PI / 512.0) * 65536.0)) +#endif + +/* Quirk: Some FM channels are output one sample later on the left side than the right. */ +#ifndef OPL_QUIRK_CHANNELSAMPLEDELAY +#define OPL_QUIRK_CHANNELSAMPLEDELAY (!OPL_ENABLE_STEREOEXT) +#endif -#define WRBUF_SIZE 1024 -#define WRBUF_DELAY 1 #define RSM_FRAC 10 // #define OPL_FREQ FREQ_48000 @@ -72,148 +85,6 @@ enum { egk_drum = 0x02 }; -enum envelope_gen_num { - envelope_gen_num_attack = 0, - envelope_gen_num_decay = 1, - envelope_gen_num_sustain = 2, - envelope_gen_num_release = 3 -}; - -struct chan; -struct chip; - -typedef struct slot { - struct chan *chan; - struct chip *dev; - int16_t out; - int16_t fbmod; - int16_t *mod; - int16_t prout; - int16_t eg_rout; - int16_t eg_out; - uint8_t eg_inc; - uint8_t eg_gen; - uint8_t eg_rate; - uint8_t eg_ksl; - uint8_t *trem; - uint8_t reg_vib; - uint8_t reg_type; - uint8_t reg_ksr; - uint8_t reg_mult; - uint8_t reg_ksl; - uint8_t reg_tl; - uint8_t reg_ar; - uint8_t reg_dr; - uint8_t reg_sl; - uint8_t reg_rr; - uint8_t reg_wf; - uint8_t key; - uint32_t pg_reset; - uint32_t pg_phase; - uint16_t pg_phase_out; - uint8_t slot_num; -} slot_t; - -typedef struct chan { - slot_t *slots[2]; - struct chan *pair; - struct chip *dev; - int16_t *out[4]; - uint8_t chtype; - uint16_t f_num; - uint8_t block; - uint8_t fb; - uint8_t con; - uint8_t alg; - uint8_t ksv; - uint16_t cha; - uint16_t chb; - uint8_t ch_num; -} chan_t; - -typedef struct wrbuf { - uint64_t time; - uint16_t reg; - uint8_t data; -} wrbuf_t; - -typedef struct chip { - chan_t chan[18]; - slot_t slot[36]; - uint16_t timer; - uint64_t eg_timer; - uint8_t eg_timerrem; - uint8_t eg_state; - uint8_t eg_add; - uint8_t newm; - uint8_t nts; - uint8_t rhy; - uint8_t vibpos; - uint8_t vibshift; - uint8_t tremolo; - uint8_t tremolopos; - uint8_t tremoloshift; - uint32_t noise; - int16_t zeromod; - int32_t mixbuff[2]; - uint8_t rm_hh_bit2; - uint8_t rm_hh_bit3; - uint8_t rm_hh_bit7; - uint8_t rm_hh_bit8; - uint8_t rm_tc_bit3; - uint8_t rm_tc_bit5; - - // OPL3L - int32_t rateratio; - int32_t samplecnt; - int32_t oldsamples[2]; - int32_t samples[2]; - - uint64_t wrbuf_samplecnt; - uint32_t wrbuf_cur; - uint32_t wrbuf_last; - uint64_t wrbuf_lasttime; - wrbuf_t wrbuf[WRBUF_SIZE]; -} nuked_t; - -typedef struct { - nuked_t opl; - int8_t flags; - int8_t pad; - - uint16_t port; - uint8_t status; - uint8_t timer_ctrl; - uint16_t timer_count[2]; - uint16_t timer_cur_count[2]; - - pc_timer_t timers[2]; - - int pos; - int32_t buffer[MUSICBUFLEN * 2]; -} nuked_drv_t; - -enum { - FLAG_CYCLES = 0x02, - FLAG_OPL3 = 0x01 -}; - -enum { - STAT_TMR_OVER = 0x60, - STAT_TMR1_OVER = 0x40, - STAT_TMR2_OVER = 0x20, - STAT_TMR_ANY = 0x80 -}; - -enum { - CTRL_RESET = 0x80, - CTRL_TMR_MASK = 0x60, - CTRL_TMR1_MASK = 0x40, - CTRL_TMR2_MASK = 0x20, - CTRL_TMR2_START = 0x02, - CTRL_TMR1_START = 0x01 -}; - #ifdef ENABLE_OPL_LOG int nuked_do_log = ENABLE_OPL_LOG; @@ -322,10 +193,10 @@ static const uint8_t kslshift[4] = { // envelope generator constants static const uint8_t eg_incstep[4][4] = { - {0, 0, 0, 0}, - { 1, 0, 0, 0}, - { 1, 0, 1, 0}, - { 1, 1, 1, 0} + { 0, 0, 0, 0 }, + { 1, 0, 0, 0 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 0 } }; // address decoding @@ -338,21 +209,30 @@ static const uint8_t ch_slot[18] = { 0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32 }; +#if OPL_ENABLE_STEREOEXT +/* + stereo extension panning table +*/ + +static int32_t panpot_lut[256]; +static uint8_t panpot_lut_build = 0; +#endif + // Envelope generator -typedef int16_t (*env_sinfunc)(uint16_t phase, uint16_t envelope); -typedef void (*env_genfunc)(slot_t *slot); +typedef int16_t (*envelope_sinfunc)(uint16_t phase, uint16_t envelope); +typedef void (*envelope_genfunc)(opl3_slot *slot); static int16_t -env_calc_exp(uint32_t level) +OPL3_EnvelopeCalcExp(uint32_t level) { if (level > 0x1fff) level = 0x1fff; - return ((exprom[level & 0xff] << 1) >> (level >> 8)); + return ((exprom[level & 0xffu] << 1) >> (level >> 8)); } static int16_t -env_calc_sin0(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin0(uint16_t phase, uint16_t envelope) { uint16_t out = 0; uint16_t neg = 0; @@ -363,15 +243,15 @@ env_calc_sin0(uint16_t phase, uint16_t env) neg = 0xffff; if (phase & 0x0100) - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xffu) ^ 0xffu]; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; - return (env_calc_exp(out + (env << 3)) ^ neg); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg); } static int16_t -env_calc_sin1(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin1(uint16_t phase, uint16_t envelope) { uint16_t out = 0; @@ -380,30 +260,30 @@ env_calc_sin1(uint16_t phase, uint16_t env) if (phase & 0x0200) out = 0x1000; else if (phase & 0x0100) - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xffu) ^ 0xffu]; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; - return (env_calc_exp(out + (env << 3))); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3))); } static int16_t -env_calc_sin2(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin2(uint16_t phase, uint16_t envelope) { uint16_t out = 0; phase &= 0x03ff; if (phase & 0x0100) - out = logsinrom[(phase & 0xff) ^ 0xff]; + out = logsinrom[(phase & 0xffu) ^ 0xffu]; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; - return (env_calc_exp(out + (env << 3))); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3))); } static int16_t -env_calc_sin3(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin3(uint16_t phase, uint16_t envelope) { uint16_t out = 0; @@ -412,13 +292,13 @@ env_calc_sin3(uint16_t phase, uint16_t env) if (phase & 0x0100) out = 0x1000; else - out = logsinrom[phase & 0xff]; + out = logsinrom[phase & 0xffu]; - return (env_calc_exp(out + (env << 3))); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3))); } static int16_t -env_calc_sin4(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin4(uint16_t phase, uint16_t envelope) { uint16_t out = 0; uint16_t neg = 0; @@ -431,15 +311,15 @@ env_calc_sin4(uint16_t phase, uint16_t env) if (phase & 0x0200) out = 0x1000; else if (phase & 0x80) - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + out = logsinrom[((phase ^ 0xffu) << 1u) & 0xffu]; else - out = logsinrom[(phase << 1) & 0xff]; + out = logsinrom[(phase << 1u) & 0xffu]; - return (env_calc_exp(out + (env << 3)) ^ neg); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg); } static int16_t -env_calc_sin5(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin5(uint16_t phase, uint16_t envelope) { uint16_t out = 0; @@ -448,15 +328,15 @@ env_calc_sin5(uint16_t phase, uint16_t env) if (phase & 0x0200) out = 0x1000; else if (phase & 0x80) - out = logsinrom[((phase ^ 0xff) << 1) & 0xff]; + out = logsinrom[((phase ^ 0xffu) << 1u) & 0xffu]; else - out = logsinrom[(phase << 1) & 0xff]; + out = logsinrom[(phase << 1u) & 0xffu]; - return (env_calc_exp(out + (env << 3))); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3))); } static int16_t -env_calc_sin6(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin6(uint16_t phase, uint16_t envelope) { uint16_t neg = 0; @@ -465,11 +345,11 @@ env_calc_sin6(uint16_t phase, uint16_t env) if (phase & 0x0200) neg = 0xffff; - return (env_calc_exp(env << 3) ^ neg); + return (OPL3_EnvelopeCalcExp(envelope << 3) ^ neg); } static int16_t -env_calc_sin7(uint16_t phase, uint16_t env) +OPL3_EnvelopeCalcSin7(uint16_t phase, uint16_t envelope) { uint16_t out = 0; uint16_t neg = 0; @@ -483,24 +363,32 @@ env_calc_sin7(uint16_t phase, uint16_t env) out = phase << 3; - return (env_calc_exp(out + (env << 3)) ^ neg); + return (OPL3_EnvelopeCalcExp(out + (envelope << 3)) ^ neg); } -static const env_sinfunc env_sin[8] = { - env_calc_sin0, - env_calc_sin1, - env_calc_sin2, - env_calc_sin3, - env_calc_sin4, - env_calc_sin5, - env_calc_sin6, - env_calc_sin7 +static const envelope_sinfunc envelope_sin[8] = { + OPL3_EnvelopeCalcSin0, + OPL3_EnvelopeCalcSin1, + OPL3_EnvelopeCalcSin2, + OPL3_EnvelopeCalcSin3, + OPL3_EnvelopeCalcSin4, + OPL3_EnvelopeCalcSin5, + OPL3_EnvelopeCalcSin6, + OPL3_EnvelopeCalcSin7 +}; + +enum envelope_gen_num { + envelope_gen_num_attack = 0, + envelope_gen_num_decay = 1, + envelope_gen_num_sustain = 2, + envelope_gen_num_release = 3 }; static void -env_update_ksl(slot_t *slot) +OPL3_EnvelopeUpdateKSL(opl3_slot *slot) { - int16_t ksl = (kslrom[slot->chan->f_num >> 6] << 2) - ((0x08 - slot->chan->block) << 5); + int16_t ksl = (kslrom[slot->channel->f_num >> 6u] << 2) + - ((0x08 - slot->channel->block) << 5); if (ksl < 0) ksl = 0; @@ -509,7 +397,7 @@ env_update_ksl(slot_t *slot) } static void -env_calc(slot_t *slot) +OPL3_EnvelopeCalc(opl3_slot *slot) { uint8_t nonzero; uint8_t rate; @@ -524,7 +412,8 @@ env_calc(slot_t *slot) uint8_t eg_off; uint8_t reset = 0; - slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; + slot->eg_out = slot->eg_rout + (slot->reg_tl << 2) + + (slot->eg_ksl >> kslshift[slot->reg_ksl]) + *slot->trem; if (slot->key && slot->eg_gen == envelope_gen_num_release) { reset = 1; reg_rate = slot->reg_ar; @@ -552,19 +441,21 @@ env_calc(slot_t *slot) } slot->pg_reset = reset; - ks = slot->chan->ksv >> ((slot->reg_ksr ^ 1) << 1); + ks = slot->channel->ksv >> ((slot->reg_ksr ^ 1) << 1); nonzero = (reg_rate != 0); rate = ks + (reg_rate << 2); rate_hi = rate >> 2; rate_lo = rate & 0x03; + if (rate_hi & 0x10) rate_hi = 0x0f; - eg_shift = rate_hi + slot->dev->eg_add; + + eg_shift = rate_hi + slot->chip->eg_add; shift = 0; if (nonzero) { if (rate_hi < 12) { - if (slot->dev->eg_state) + if (slot->chip->eg_state) switch (eg_shift) { case 12: shift = 1; @@ -582,11 +473,11 @@ env_calc(slot_t *slot) break; } } else { - shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->dev->timer & 0x03]; + shift = (rate_hi & 0x03) + eg_incstep[rate_lo][slot->chip->eg_timer_lo]; if (shift & 0x04) shift = 0x03; if (!shift) - shift = slot->dev->eg_state; + shift = slot->chip->eg_state; } } @@ -610,7 +501,7 @@ env_calc(slot_t *slot) if (!slot->eg_rout) slot->eg_gen = envelope_gen_num_decay; else if (slot->key && shift > 0 && rate_hi != 0x0f) - eg_inc = ((~slot->eg_rout) << shift) >> 4; + eg_inc = ~slot->eg_rout >> (4 - shift); break; case envelope_gen_num_decay: @@ -640,48 +531,50 @@ env_calc(slot_t *slot) } static void -env_key_on(slot_t *slot, uint8_t type) +OPL3_EnvelopeKeyOn(opl3_slot *slot, uint8_t type) { slot->key |= type; } static void -env_key_off(slot_t *slot, uint8_t type) +OPL3_EnvelopeKeyOff(opl3_slot *slot, uint8_t type) { slot->key &= ~type; } +// Phase Generator static void -phase_generate(slot_t *slot) +OPL3_PhaseGenerate(opl3_slot *slot) { - uint16_t f_num; - uint32_t basefreq; - uint8_t rm_xor; - uint8_t n_bit; - uint32_t noise; - uint16_t phase; - int8_t range; - uint8_t vibpos; - nuked_t *dev; - - dev = slot->dev; - f_num = slot->chan->f_num; + opl3_chip *chip; + uint16_t f_num; + uint32_t basefreq; + uint8_t rm_xor; + uint8_t n_bit; + uint32_t noise; + uint16_t phase; + + chip = slot->chip; + f_num = slot->channel->f_num; if (slot->reg_vib) { + int8_t range; + uint8_t vibpos; + range = (f_num >> 7) & 7; - vibpos = dev->vibpos; + vibpos = chip->vibpos; if (!(vibpos & 3)) range = 0; else if (vibpos & 1) range >>= 1; - range >>= dev->vibshift; + range >>= chip->vibshift; if (vibpos & 4) range = -range; f_num += range; } - basefreq = (f_num << slot->chan->block) >> 1; + basefreq = (f_num << slot->channel->block) >> 1; phase = (uint16_t) (slot->pg_phase >> 9); if (slot->pg_reset) @@ -689,20 +582,22 @@ phase_generate(slot_t *slot) slot->pg_phase += (basefreq * mt[slot->reg_mult]) >> 1; // Rhythm mode - noise = dev->noise; + noise = chip->noise; slot->pg_phase_out = phase; if (slot->slot_num == 13) { // hh - dev->rm_hh_bit2 = (phase >> 2) & 1; - dev->rm_hh_bit3 = (phase >> 3) & 1; - dev->rm_hh_bit7 = (phase >> 7) & 1; - dev->rm_hh_bit8 = (phase >> 8) & 1; + chip->rm_hh_bit2 = (phase >> 2) & 1; + chip->rm_hh_bit3 = (phase >> 3) & 1; + chip->rm_hh_bit7 = (phase >> 7) & 1; + chip->rm_hh_bit8 = (phase >> 8) & 1; } - if (slot->slot_num == 17 && (dev->rhy & 0x20)) { // tc - dev->rm_tc_bit3 = (phase >> 3) & 1; - dev->rm_tc_bit5 = (phase >> 5) & 1; + if (slot->slot_num == 17 && (chip->rhy & 0x20)) { // tc + chip->rm_tc_bit3 = (phase >> 3) & 1; + chip->rm_tc_bit5 = (phase >> 5) & 1; } - if (dev->rhy & 0x20) { - rm_xor = (dev->rm_hh_bit2 ^ dev->rm_hh_bit7) | (dev->rm_hh_bit3 ^ dev->rm_tc_bit5) | (dev->rm_tc_bit3 ^ dev->rm_tc_bit5); + if (chip->rhy & 0x20) { + rm_xor = (chip->rm_hh_bit2 ^ chip->rm_hh_bit7) + | (chip->rm_hh_bit3 ^ chip->rm_tc_bit5) + | (chip->rm_tc_bit3 ^ chip->rm_tc_bit5); switch (slot->slot_num) { case 13: // hh @@ -714,7 +609,8 @@ phase_generate(slot_t *slot) break; case 16: // sd - slot->pg_phase_out = (dev->rm_hh_bit8 << 9) | ((dev->rm_hh_bit8 ^ (noise & 1)) << 8); + slot->pg_phase_out = (chip->rm_hh_bit8 << 9) + | ((chip->rm_hh_bit8 ^ (noise & 1)) << 8); break; case 17: // tc @@ -728,16 +624,17 @@ phase_generate(slot_t *slot) n_bit = ((noise >> 14) ^ noise) & 0x01; - dev->noise = (noise >> 1) | (n_bit << 22); + chip->noise = (noise >> 1) | (n_bit << 22); } +// Slot static void -slot_write_20(slot_t *slot, uint8_t data) +OPL3_SlotWrite20(opl3_slot *slot, uint8_t data) { if ((data >> 7) & 0x01) - slot->trem = &slot->dev->tremolo; + slot->trem = &slot->chip->tremolo; else - slot->trem = (uint8_t *) &slot->dev->zeromod; + slot->trem = (uint8_t *) &slot->chip->zeromod; slot->reg_vib = (data >> 6) & 0x01; slot->reg_type = (data >> 5) & 0x01; @@ -746,23 +643,23 @@ slot_write_20(slot_t *slot, uint8_t data) } static void -slot_write_40(slot_t *slot, uint8_t data) +OPL3_SlotWrite40(opl3_slot *slot, uint8_t data) { slot->reg_ksl = (data >> 6) & 0x03; slot->reg_tl = data & 0x3f; - env_update_ksl(slot); + OPL3_EnvelopeUpdateKSL(slot); } static void -slot_write_60(slot_t *slot, uint8_t data) +OPL3_SlotWrite60(opl3_slot *slot, uint8_t data) { slot->reg_ar = (data >> 4) & 0x0f; slot->reg_dr = data & 0x0f; } static void -slot_write_80(slot_t *slot, uint8_t data) +OPL3_SlotWrite80(opl3_slot *slot, uint8_t data) { slot->reg_sl = (data >> 4) & 0x0f; @@ -773,51 +670,176 @@ slot_write_80(slot_t *slot, uint8_t data) } static void -slot_write_e0(slot_t *slot, uint8_t data) +OPL3_SlotWriteE0(opl3_slot *slot, uint8_t data) { slot->reg_wf = data & 0x07; - if (slot->dev->newm == 0x00) + if (slot->chip->newm == 0x00) slot->reg_wf &= 0x03; } static void -slot_generate(slot_t *slot) +OPL3_SlotGenerate(opl3_slot *slot) { - slot->out = env_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, - slot->eg_out); + slot->out = envelope_sin[slot->reg_wf](slot->pg_phase_out + *slot->mod, slot->eg_out); } static void -slot_calc_fb(slot_t *slot) +OPL3_SlotCalcFB(opl3_slot *slot) { - if (slot->chan->fb != 0x00) - slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->chan->fb); + if (slot->channel->fb != 0x00) + slot->fbmod = (slot->prout + slot->out) >> (0x09 - slot->channel->fb); else slot->fbmod = 0; slot->prout = slot->out; } +// Channel +static void +OPL3_ChannelSetupAlg(opl3_channel *channel); + +static void +OPL3_ChannelUpdateRhythm(opl3_chip *chip, uint8_t data) +{ + opl3_channel *channel6; + opl3_channel *channel7; + opl3_channel *channel8; + uint8_t chnum; + + chip->rhy = data & 0x3f; + if (chip->rhy & 0x20) { + channel6 = &chip->channel[6]; + channel7 = &chip->channel[7]; + channel8 = &chip->channel[8]; + channel6->out[0] = &channel6->slotz[1]->out; + channel6->out[1] = &channel6->slotz[1]->out; + channel6->out[2] = &chip->zeromod; + channel6->out[3] = &chip->zeromod; + channel7->out[0] = &channel7->slotz[0]->out; + channel7->out[1] = &channel7->slotz[0]->out; + channel7->out[2] = &channel7->slotz[1]->out; + channel7->out[3] = &channel7->slotz[1]->out; + channel8->out[0] = &channel8->slotz[0]->out; + channel8->out[1] = &channel8->slotz[0]->out; + channel8->out[2] = &channel8->slotz[1]->out; + channel8->out[3] = &channel8->slotz[1]->out; + + for (chnum = 6; chnum < 9; chnum++) + chip->channel[chnum].chtype = ch_drum; + + OPL3_ChannelSetupAlg(channel6); + OPL3_ChannelSetupAlg(channel7); + OPL3_ChannelSetupAlg(channel8); + + // hh + if (chip->rhy & 0x01) + OPL3_EnvelopeKeyOn(channel7->slotz[0], egk_drum); + else + OPL3_EnvelopeKeyOff(channel7->slotz[0], egk_drum); + + // tc + if (chip->rhy & 0x02) + OPL3_EnvelopeKeyOn(channel8->slotz[1], egk_drum); + else + OPL3_EnvelopeKeyOff(channel8->slotz[1], egk_drum); + + // tom + if (chip->rhy & 0x04) + OPL3_EnvelopeKeyOn(channel8->slotz[0], egk_drum); + else + OPL3_EnvelopeKeyOff(channel8->slotz[0], egk_drum); + + // sd + if (chip->rhy & 0x08) + OPL3_EnvelopeKeyOn(channel7->slotz[1], egk_drum); + else + OPL3_EnvelopeKeyOff(channel7->slotz[1], egk_drum); + + // bd + if (chip->rhy & 0x10) { + OPL3_EnvelopeKeyOn(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOn(channel6->slotz[1], egk_drum); + } else { + OPL3_EnvelopeKeyOff(channel6->slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(channel6->slotz[1], egk_drum); + } + } else { + for (chnum = 6; chnum < 9; chnum++) { + chip->channel[chnum].chtype = ch_2op; + + OPL3_ChannelSetupAlg(&chip->channel[chnum]); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[0], egk_drum); + OPL3_EnvelopeKeyOff(chip->channel[chnum].slotz[1], egk_drum); + } + } +} + +static void +OPL3_ChannelWriteA0(opl3_channel *channel, uint8_t data) +{ + if (channel->chip->newm && channel->chtype == ch_4op2) + return; + + channel->f_num = (channel->f_num & 0x300) | data; + channel->ksv = (channel->block << 1) + | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); + + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); + + if (channel->chip->newm && channel->chtype == ch_4op) { + channel->pair->f_num = channel->f_num; + channel->pair->ksv = channel->ksv; + + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); + } +} + static void -channel_setup_alg(chan_t *ch) +OPL3_ChannelWriteB0(opl3_channel *channel, uint8_t data) { - if (ch->chtype == ch_drum) { - if (ch->ch_num == 7 || ch->ch_num == 8) { - ch->slots[0]->mod = &ch->dev->zeromod; - ch->slots[1]->mod = &ch->dev->zeromod; + if (channel->chip->newm && channel->chtype == ch_4op2) + return; + + channel->f_num = (channel->f_num & 0xff) | ((data & 0x03) << 8); + channel->block = (data >> 2) & 0x07; + channel->ksv = (channel->block << 1) + | ((channel->f_num >> (0x09 - channel->chip->nts)) & 0x01); + + OPL3_EnvelopeUpdateKSL(channel->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->slotz[1]); + + if (channel->chip->newm && channel->chtype == ch_4op) { + channel->pair->f_num = channel->f_num; + channel->pair->block = channel->block; + channel->pair->ksv = channel->ksv; + + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[0]); + OPL3_EnvelopeUpdateKSL(channel->pair->slotz[1]); + } +} + +static void +OPL3_ChannelSetupAlg(opl3_channel *channel) +{ + if (channel->chtype == ch_drum) { + if (channel->ch_num == 7 || channel->ch_num == 8) { + channel->slotz[0]->mod = &channel->chip->zeromod; + channel->slotz[1]->mod = &channel->chip->zeromod; return; } - switch (ch->alg & 0x01) { + switch (channel->alg & 0x01) { case 0x00: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->slots[0]->out; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; break; case 0x01: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->dev->zeromod; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->chip->zeromod; break; default: @@ -826,81 +848,81 @@ channel_setup_alg(chan_t *ch) return; } - if (ch->alg & 0x08) + if (channel->alg & 0x08) return; - if (ch->alg & 0x04) { - ch->pair->out[0] = &ch->dev->zeromod; - ch->pair->out[1] = &ch->dev->zeromod; - ch->pair->out[2] = &ch->dev->zeromod; - ch->pair->out[3] = &ch->dev->zeromod; + if (channel->alg & 0x04) { + channel->pair->out[0] = &channel->chip->zeromod; + channel->pair->out[1] = &channel->chip->zeromod; + channel->pair->out[2] = &channel->chip->zeromod; + channel->pair->out[3] = &channel->chip->zeromod; - switch (ch->alg & 0x03) { + switch (channel->alg & 0x03) { case 0x00: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->pair->slots[0]->out; - ch->slots[0]->mod = &ch->pair->slots[1]->out; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->slots[1]->out; - ch->out[1] = &ch->dev->zeromod; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; + channel->out[1] = &channel->chip->zeromod; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; break; case 0x01: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->pair->slots[0]->out; - ch->slots[0]->mod = &ch->dev->zeromod; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->pair->slots[1]->out; - ch->out[1] = &ch->slots[1]->out; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->pair->slotz[0]->out; + channel->slotz[0]->mod = &channel->chip->zeromod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[1]->out; + channel->out[1] = &channel->slotz[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; break; case 0x02: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->dev->zeromod; - ch->slots[0]->mod = &ch->pair->slots[1]->out; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->pair->slots[0]->out; - ch->out[1] = &ch->slots[1]->out; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; break; case 0x03: - ch->pair->slots[0]->mod = &ch->pair->slots[0]->fbmod; - ch->pair->slots[1]->mod = &ch->dev->zeromod; - ch->slots[0]->mod = &ch->pair->slots[1]->out; - ch->slots[1]->mod = &ch->dev->zeromod; - ch->out[0] = &ch->pair->slots[0]->out; - ch->out[1] = &ch->slots[0]->out; - ch->out[2] = &ch->slots[1]->out; - ch->out[3] = &ch->dev->zeromod; + channel->pair->slotz[0]->mod = &channel->pair->slotz[0]->fbmod; + channel->pair->slotz[1]->mod = &channel->chip->zeromod; + channel->slotz[0]->mod = &channel->pair->slotz[1]->out; + channel->slotz[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->pair->slotz[0]->out; + channel->out[1] = &channel->slotz[0]->out; + channel->out[2] = &channel->slotz[1]->out; + channel->out[3] = &channel->chip->zeromod; break; default: break; } } else - switch (ch->alg & 0x01) { + switch (channel->alg & 0x01) { case 0x00: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->slots[0]->out; - ch->out[0] = &ch->slots[1]->out; - ch->out[1] = &ch->dev->zeromod; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->slotz[0]->out; + channel->out[0] = &channel->slotz[1]->out; + channel->out[1] = &channel->chip->zeromod; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; break; case 0x01: - ch->slots[0]->mod = &ch->slots[0]->fbmod; - ch->slots[1]->mod = &ch->dev->zeromod; - ch->out[0] = &ch->slots[0]->out; - ch->out[1] = &ch->slots[1]->out; - ch->out[2] = &ch->dev->zeromod; - ch->out[3] = &ch->dev->zeromod; + channel->slotz[0]->mod = &channel->slotz[0]->fbmod; + channel->slotz[1]->mod = &channel->chip->zeromod; + channel->out[0] = &channel->slotz[0]->out; + channel->out[1] = &channel->slotz[1]->out; + channel->out[2] = &channel->chip->zeromod; + channel->out[3] = &channel->chip->zeromod; break; default: @@ -909,242 +931,397 @@ channel_setup_alg(chan_t *ch) } static void -channel_update_rhythm(nuked_t *dev, uint8_t data) +OPL3_ChannelUpdateAlg(opl3_channel *channel) { - chan_t *ch6; - chan_t *ch7; - chan_t *ch8; - uint8_t chnum; - - dev->rhy = data & 0x3f; - if (dev->rhy & 0x20) { - ch6 = &dev->chan[6]; - ch7 = &dev->chan[7]; - ch8 = &dev->chan[8]; - ch6->out[0] = &ch6->slots[1]->out; - ch6->out[1] = &ch6->slots[1]->out; - ch6->out[2] = &dev->zeromod; - ch6->out[3] = &dev->zeromod; - ch7->out[0] = &ch7->slots[0]->out; - ch7->out[1] = &ch7->slots[0]->out; - ch7->out[2] = &ch7->slots[1]->out; - ch7->out[3] = &ch7->slots[1]->out; - ch8->out[0] = &ch8->slots[0]->out; - ch8->out[1] = &ch8->slots[0]->out; - ch8->out[2] = &ch8->slots[1]->out; - ch8->out[3] = &ch8->slots[1]->out; - - for (chnum = 6; chnum < 9; chnum++) - dev->chan[chnum].chtype = ch_drum; - - channel_setup_alg(ch6); - channel_setup_alg(ch7); - channel_setup_alg(ch8); - - // hh - if (dev->rhy & 0x01) - env_key_on(ch7->slots[0], egk_drum); - else - env_key_off(ch7->slots[0], egk_drum); + channel->alg = channel->con; + + if (channel->chip->newm) { + if (channel->chtype == ch_4op) { + channel->pair->alg = 0x04 | (channel->con << 1) | (channel->pair->con); + channel->alg = 0x08; + OPL3_ChannelSetupAlg(channel->pair); + } else if (channel->chtype == ch_4op2) { + channel->alg = 0x04 | (channel->pair->con << 1) | (channel->con); + channel->pair->alg = 0x08; + OPL3_ChannelSetupAlg(channel); + } else + OPL3_ChannelSetupAlg(channel); + } else + OPL3_ChannelSetupAlg(channel); +} - // tc - if (dev->rhy & 0x02) - env_key_on(ch8->slots[1], egk_drum); - else - env_key_off(ch8->slots[1], egk_drum); +static void +OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data) +{ + channel->fb = (data & 0x0e) >> 1; + channel->con = data & 0x01; + OPL3_ChannelUpdateAlg(channel); + + if (channel->chip->newm) { + channel->cha = ((data >> 4) & 0x01) ? ~0 : 0; + channel->chb = ((data >> 5) & 0x01) ? ~0 : 0; + channel->chc = ((data >> 6) & 0x01) ? ~0 : 0; + channel->chd = ((data >> 7) & 0x01) ? ~0 : 0; + } else { + channel->cha = channel->chb = (uint16_t) ~0; + // TODO: Verify on real chip if DAC2 output is disabled in compat mode + channel->chc = channel->chd = 0; + } - // tom - if (dev->rhy & 0x04) - env_key_on(ch8->slots[0], egk_drum); - else - env_key_off(ch8->slots[0], egk_drum); +#if OPL_ENABLE_STEREOEXT + if (!channel->chip->stereoext) { + channel->leftpan = channel->cha << 16; + channel->rightpan = channel->chb << 16; + } +#endif +} - // sd - if (dev->rhy & 0x08) - env_key_on(ch7->slots[1], egk_drum); - else - env_key_off(ch7->slots[1], egk_drum); +#if OPL_ENABLE_STEREOEXT +static void +OPL3_ChannelWriteD0(opl3_channel *channel, uint8_t data) +{ + if (channel->chip->stereoext) { + channel->leftpan = panpot_lut[data ^ 0xffu]; + channel->rightpan = panpot_lut[data]; + } +} +#endif - // bd - if (dev->rhy & 0x10) { - env_key_on(ch6->slots[0], egk_drum); - env_key_on(ch6->slots[1], egk_drum); - } else { - env_key_off(ch6->slots[0], egk_drum); - env_key_off(ch6->slots[1], egk_drum); +static void +OPL3_ChannelKeyOn(opl3_channel *channel) +{ + if (channel->chip->newm) { + if (channel->chtype == ch_4op) { + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->pair->slotz[1], egk_norm); + } else if (channel->chtype == ch_2op || channel->chtype == ch_drum) { + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); } } else { - for (chnum = 6; chnum < 9; chnum++) { - dev->chan[chnum].chtype = ch_2op; + OPL3_EnvelopeKeyOn(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOn(channel->slotz[1], egk_norm); + } +} - channel_setup_alg(&dev->chan[chnum]); - env_key_off(dev->chan[chnum].slots[0], egk_drum); - env_key_off(dev->chan[chnum].slots[1], egk_drum); +static void +OPL3_ChannelKeyOff(opl3_channel *channel) +{ + if (channel->chip->newm) { + if (channel->chtype == ch_4op) { + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->pair->slotz[1], egk_norm); + } else if (channel->chtype == ch_2op || channel->chtype == ch_drum) { + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); } + } else { + OPL3_EnvelopeKeyOff(channel->slotz[0], egk_norm); + OPL3_EnvelopeKeyOff(channel->slotz[1], egk_norm); } } static void -channel_write_a0(chan_t *ch, uint8_t data) +OPL3_ChannelSet4Op(opl3_chip *chip, uint8_t data) { - if (ch->dev->newm && ch->chtype == ch_4op2) - return; - - ch->f_num = (ch->f_num & 0x300) | data; - ch->ksv = (ch->block << 1) | ((ch->f_num >> (0x09 - ch->dev->nts)) & 0x01); + uint8_t chnum; - env_update_ksl(ch->slots[0]); - env_update_ksl(ch->slots[1]); + for (uint8_t bit = 0; bit < 6; bit++) { + chnum = bit; - if (ch->dev->newm && ch->chtype == ch_4op) { - ch->pair->f_num = ch->f_num; - ch->pair->ksv = ch->ksv; + if (bit >= 3) + chnum += 9 - 3; - env_update_ksl(ch->pair->slots[0]); - env_update_ksl(ch->pair->slots[1]); + if ((data >> bit) & 0x01) { + chip->channel[chnum].chtype = ch_4op; + chip->channel[chnum + 3u].chtype = ch_4op2; + OPL3_ChannelUpdateAlg(&chip->channel[chnum]); + } else { + chip->channel[chnum].chtype = ch_2op; + chip->channel[chnum + 3u].chtype = ch_2op; + OPL3_ChannelUpdateAlg(&chip->channel[chnum]); + OPL3_ChannelUpdateAlg(&chip->channel[chnum + 3u]); + } } } static void -channel_write_b0(chan_t *ch, uint8_t data) +OPL3_ProcessSlot(opl3_slot *slot) { - if (ch->dev->newm && ch->chtype == ch_4op2) - return; + OPL3_SlotCalcFB(slot); + OPL3_EnvelopeCalc(slot); + OPL3_PhaseGenerate(slot); + OPL3_SlotGenerate(slot); +} - ch->f_num = (ch->f_num & 0xff) | ((data & 0x03) << 8); - ch->block = (data >> 2) & 0x07; - ch->ksv = (ch->block << 1) | ((ch->f_num >> (0x09 - ch->dev->nts)) & 0x01); +static inline void +OPL3_Generate4Ch(void *priv, int32_t *buf4) +{ + opl3_chip *chip = (opl3_chip *) priv; + opl3_channel *channel; + opl3_writebuf *writebuf; + int16_t **out; + int32_t mix[2]; + uint8_t i; + int16_t accm; + uint8_t shift = 0; + + buf4[1] = chip->mixbuff[1]; + buf4[3] = chip->mixbuff[3]; + +#if OPL_QUIRK_CHANNELSAMPLEDELAY + for (i = 0; i < 15; i++) +#else + for (i = 0; i < 36; i++) +#endif + OPL3_ProcessSlot(&chip->slot[i]); - env_update_ksl(ch->slots[0]); - env_update_ksl(ch->slots[1]); + mix[0] = mix[1] = 0; - if (ch->dev->newm && ch->chtype == ch_4op) { - ch->pair->f_num = ch->f_num; - ch->pair->block = ch->block; - ch->pair->ksv = ch->ksv; + for (i = 0; i < 18; i++) { + channel = &chip->channel[i]; + out = channel->out; + accm = *out[0] + *out[1] + *out[2] + *out[3]; +#if OPL_ENABLE_STEREOEXT + mix[0] += (int16_t) ((accm * channel->leftpan) >> 16); +#else + mix[0] += (int16_t) (accm & channel->cha); +#endif + mix[1] += (int16_t) (accm & channel->chc); + } + + chip->mixbuff[0] = mix[0]; + chip->mixbuff[2] = mix[1]; + +#if OPL_QUIRK_CHANNELSAMPLEDELAY + for (i = 15; i < 18; i++) + OPL3_ProcessSlot(&chip->slot[i]); +#endif + + buf4[0] = chip->mixbuff[0]; + buf4[2] = chip->mixbuff[2]; + +#if OPL_QUIRK_CHANNELSAMPLEDELAY + for (i = 18; i < 33; i++) + OPL3_ProcessSlot(&chip->slot[i]); +#endif + + mix[0] = mix[1] = 0; - env_update_ksl(ch->pair->slots[0]); - env_update_ksl(ch->pair->slots[1]); + for (i = 0; i < 18; i++) { + channel = &chip->channel[i]; + out = channel->out; + accm = *out[0] + *out[1] + *out[2] + *out[3]; +#if OPL_ENABLE_STEREOEXT + mix[0] += (int16_t) ((accm * channel->rightpan) >> 16); +#else + mix[0] += (int16_t) (accm & channel->chb); +#endif + mix[1] += (int16_t) (accm & channel->chd); } + + chip->mixbuff[1] = mix[0]; + chip->mixbuff[3] = mix[1]; + +#if OPL_QUIRK_CHANNELSAMPLEDELAY + for (i = 33; i < 36; i++) + OPL3_ProcessSlot(&chip->slot[i]); +#endif + + if ((chip->timer & 0x3f) == 0x3f) + chip->tremolopos = (chip->tremolopos + 1) % 210; + + if (chip->tremolopos < 105) + chip->tremolo = chip->tremolopos >> chip->tremoloshift; + else + chip->tremolo = (210 - chip->tremolopos) >> chip->tremoloshift; + + if ((chip->timer & 0x03ff) == 0x03ff) + chip->vibpos = (chip->vibpos + 1) & 7; + + chip->timer++; + + if (chip->eg_state) { + while (shift < 13 && ((chip->eg_timer >> shift) & 1) == 0) + shift++; + + if (shift > 12) + chip->eg_add = 0; + else + chip->eg_add = shift + 1; + + chip->eg_timer_lo = (uint8_t) (chip->eg_timer & 0x3u); + } + + if (chip->eg_timerrem || chip->eg_state) { + if (chip->eg_timer == UINT64_C(0xfffffffff)) { + chip->eg_timer = 0; + chip->eg_timerrem = 1; + } else { + chip->eg_timer++; + chip->eg_timerrem = 0; + } + } + + chip->eg_state ^= 1; + + while ((writebuf = &chip->writebuf[chip->writebuf_cur]), writebuf->time <= chip->writebuf_samplecnt) { + if (!(writebuf->reg & 0x200)) + break; + + writebuf->reg &= 0x01ff; + + OPL3_WriteReg(chip, writebuf->reg, writebuf->data); + + chip->writebuf_cur = (chip->writebuf_cur + 1) % OPL_WRITEBUF_SIZE; + } + + chip->writebuf_samplecnt++; } -static void -channel_write_c0(chan_t *ch, uint8_t data) +void +OPL3_Generate(opl3_chip *chip, int32_t *buf) { - ch->fb = (data & 0x0e) >> 1; - ch->con = data & 0x01; - ch->alg = ch->con; - - if (ch->dev->newm) { - if (ch->chtype == ch_4op) { - ch->pair->alg = 0x04 | (ch->con << 1) | ch->pair->con; - ch->alg = 0x08; - channel_setup_alg(ch->pair); - } else if (ch->chtype == ch_4op2) { - ch->alg = 0x04 | (ch->pair->con << 1) | ch->con; - ch->pair->alg = 0x08; - channel_setup_alg(ch); - } else - channel_setup_alg(ch); - } else - channel_setup_alg(ch); - - if (ch->dev->newm) { - ch->cha = ((data >> 4) & 0x01) ? ~0 : 0; - ch->chb = ((data >> 5) & 0x01) ? ~0 : 0; - } else - ch->cha = ch->chb = (uint16_t) ~0; + int32_t samples[4]; + OPL3_Generate4Ch(chip, samples); + buf[0] = samples[0]; + buf[1] = samples[1]; } -static void -channel_key_on(chan_t *ch) +void +OPL3_Generate4ChResampled(opl3_chip *chip, int32_t *buf4) { - if (ch->dev->newm) { - if (ch->chtype == ch_4op) { - env_key_on(ch->slots[0], egk_norm); - env_key_on(ch->slots[1], egk_norm); - env_key_on(ch->pair->slots[0], egk_norm); - env_key_on(ch->pair->slots[1], egk_norm); - } else if (ch->chtype == ch_2op || ch->chtype == ch_drum) { - env_key_on(ch->slots[0], egk_norm); - env_key_on(ch->slots[1], egk_norm); - } - } else { - env_key_on(ch->slots[0], egk_norm); - env_key_on(ch->slots[1], egk_norm); + while (chip->samplecnt >= chip->rateratio) { + chip->oldsamples[0] = chip->samples[0]; + chip->oldsamples[1] = chip->samples[1]; + chip->oldsamples[2] = chip->samples[2]; + chip->oldsamples[3] = chip->samples[3]; + OPL3_Generate4Ch(chip, chip->samples); + chip->samplecnt -= chip->rateratio; } + + buf4[0] = (int32_t) ((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt) + + chip->samples[0] * chip->samplecnt) / chip->rateratio); + buf4[1] = (int32_t) ((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt) + + chip->samples[1] * chip->samplecnt) / chip->rateratio); + buf4[2] = (int32_t) ((chip->oldsamples[2] * (chip->rateratio - chip->samplecnt) + + chip->samples[2] * chip->samplecnt) / chip->rateratio); + buf4[3] = (int32_t) ((chip->oldsamples[3] * (chip->rateratio - chip->samplecnt) + + chip->samples[3] * chip->samplecnt) / chip->rateratio); + + chip->samplecnt += 1 << RSM_FRAC; } -static void -channel_key_off(chan_t *ch) +void +OPL3_GenerateResampled(opl3_chip *chip, int32_t *buf) { - if (ch->dev->newm) { - if (ch->chtype == ch_4op) { - env_key_off(ch->slots[0], egk_norm); - env_key_off(ch->slots[1], egk_norm); - env_key_off(ch->pair->slots[0], egk_norm); - env_key_off(ch->pair->slots[1], egk_norm); - } else if (ch->chtype == ch_2op || ch->chtype == ch_drum) { - env_key_off(ch->slots[0], egk_norm); - env_key_off(ch->slots[1], egk_norm); - } - } else { - env_key_off(ch->slots[0], egk_norm); - env_key_off(ch->slots[1], egk_norm); - } + int32_t samples[4]; + OPL3_Generate4ChResampled(chip, samples); + buf[0] = samples[0]; + buf[1] = samples[1]; } -static void -channel_set_4op(nuked_t *dev, uint8_t data) +void +OPL3_Reset(opl3_chip *chip, uint32_t samplerate) { - uint8_t chnum; + opl3_slot *slot; + opl3_channel *channel; + uint8_t local_ch_slot; + + memset(chip, 0x00, sizeof(opl3_chip)); + + for (uint8_t slotnum = 0; slotnum < 36; slotnum++) { + slot = &chip->slot[slotnum]; + slot->chip = chip; + slot->mod = &chip->zeromod; + slot->eg_rout = 0x01ff; + slot->eg_out = 0x01ff; + slot->eg_gen = envelope_gen_num_release; + slot->trem = (uint8_t *) &chip->zeromod; + slot->slot_num = slotnum; + } - for (uint8_t bit = 0; bit < 6; bit++) { - chnum = bit; + for (uint8_t channum = 0; channum < 18; channum++) { + channel = &chip->channel[channum]; + local_ch_slot = ch_slot[channum]; + channel->slotz[0] = &chip->slot[local_ch_slot]; + channel->slotz[1] = &chip->slot[local_ch_slot + 3u]; + chip->slot[local_ch_slot].channel = channel; + chip->slot[local_ch_slot + 3u].channel = channel; + + if ((channum % 9) < 3) + channel->pair = &chip->channel[channum + 3u]; + else if ((channum % 9) < 6) + channel->pair = &chip->channel[channum - 3u]; + + channel->chip = chip; + channel->out[0] = &chip->zeromod; + channel->out[1] = &chip->zeromod; + channel->out[2] = &chip->zeromod; + channel->out[3] = &chip->zeromod; + channel->chtype = ch_2op; + channel->cha = 0xffff; + channel->chb = 0xffff; +#if OPL_ENABLE_STEREOEXT + channel->leftpan = 0x10000; + channel->rightpan = 0x10000; +#endif + channel->ch_num = channum; - if (bit >= 3) - chnum += 9 - 3; + OPL3_ChannelSetupAlg(channel); + } - if ((data >> bit) & 0x01) { - dev->chan[chnum].chtype = ch_4op; - dev->chan[chnum + 3].chtype = ch_4op2; - } else { - dev->chan[chnum].chtype = ch_2op; - dev->chan[chnum + 3].chtype = ch_2op; - } + chip->noise = 1; + chip->rateratio = (samplerate << RSM_FRAC) / 49716; + chip->tremoloshift = 4; + chip->vibshift = 1; + +#if OPL_ENABLE_STEREOEXT + if (!panpot_lut_build) { + for (int32_t i = 0; i < 256; i++) + panpot_lut[i] = OPL_SIN(i); + panpot_lut_build = 1; } +#endif } uint16_t nuked_write_addr(void *priv, uint16_t port, uint8_t val) { - const nuked_t *dev = (nuked_t *) priv; + const opl3_chip *chip = (opl3_chip *) priv; uint16_t addr; addr = val; - if ((port & 0x0002) && ((addr == 0x0005) || dev->newm)) + if ((port & 0x0002) && ((addr == 0x0005) || chip->newm)) addr |= 0x0100; return addr; } void -nuked_write_reg(void *priv, uint16_t reg, uint8_t val) +OPL3_WriteReg(void *priv, uint16_t reg, uint8_t val) { - nuked_t *dev = (nuked_t *) priv; - uint8_t high = (reg >> 8) & 0x01; - uint8_t regm = reg & 0xff; + opl3_chip *chip = (opl3_chip *) priv; + uint8_t high = (reg >> 8) & 0x01; + uint8_t regm = reg & 0xff; switch (regm & 0xf0) { case 0x00: if (high) switch (regm & 0x0f) { case 0x04: - channel_set_4op(dev, val); + OPL3_ChannelSet4Op(chip, val); break; case 0x05: - dev->newm = val & 0x01; + chip->newm = val & 0x01; +#if OPL_ENABLE_STEREOEXT + chip->stereoext = (val >> 1) & 0x01; +#endif break; default: @@ -1153,7 +1330,7 @@ nuked_write_reg(void *priv, uint16_t reg, uint8_t val) else switch (regm & 0x0f) { case 0x08: - dev->nts = (val >> 6) & 0x01; + chip->nts = (val >> 6) & 0x01; break; default: @@ -1163,58 +1340,65 @@ nuked_write_reg(void *priv, uint16_t reg, uint8_t val) case 0x20: case 0x30: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_20(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + if (ad_slot[regm & 0x1fu] >= 0) + OPL3_SlotWrite20(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], val); break; case 0x40: case 0x50: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_40(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + if (ad_slot[regm & 0x1fu] >= 0) + OPL3_SlotWrite40(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], val); break; case 0x60: case 0x70: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_60(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + if (ad_slot[regm & 0x1fu] >= 0) + OPL3_SlotWrite60(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], val); break; case 0x80: case 0x90: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_80(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); + if (ad_slot[regm & 0x1fu] >= 0) + OPL3_SlotWrite80(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], val); + break; + + case 0xe0: + case 0xf0: + if (ad_slot[regm & 0x1fu] >= 0) + OPL3_SlotWriteE0(&chip->slot[18u * high + ad_slot[regm & 0x1fu]], val); break; case 0xa0: if ((regm & 0x0f) < 9) - channel_write_a0(&dev->chan[9 * high + (regm & 0x0f)], val); + OPL3_ChannelWriteA0(&chip->channel[9u * high + (regm & 0x0fu)], val); break; case 0xb0: if (regm == 0xbd && !high) { - dev->tremoloshift = (((val >> 7) ^ 1) << 1) + 2; - dev->vibshift = ((val >> 6) & 0x01) ^ 1; - channel_update_rhythm(dev, val); + chip->tremoloshift = (((val >> 7) ^ 1) << 1) + 2; + chip->vibshift = ((val >> 6) & 0x01) ^ 1; + OPL3_ChannelUpdateRhythm(chip, val); } else if ((regm & 0x0f) < 9) { - channel_write_b0(&dev->chan[9 * high + (regm & 0x0f)], val); + OPL3_ChannelWriteB0(&chip->channel[9u * high + (regm & 0x0fu)], val); if (val & 0x20) - channel_key_on(&dev->chan[9 * high + (regm & 0x0f)]); + OPL3_ChannelKeyOn(&chip->channel[9u * high + (regm & 0x0fu)]); else - channel_key_off(&dev->chan[9 * high + (regm & 0x0f)]); + OPL3_ChannelKeyOff(&chip->channel[9u * high + (regm & 0x0fu)]); } break; case 0xc0: if ((regm & 0x0f) < 9) - channel_write_c0(&dev->chan[9 * high + (regm & 0x0f)], val); + OPL3_ChannelWriteC0(&chip->channel[9u * high + (regm & 0x0fu)], val); break; - case 0xe0: - case 0xf0: - if (ad_slot[regm & 0x1f] >= 0) - slot_write_e0(&dev->slot[18 * high + ad_slot[regm & 0x1f]], val); +#if OPL_ENABLE_STEREOEXT + case 0xd0: + if ((regm & 0x0f) < 9) + OPL3_ChannelWriteD0(&chip->channel[9u * high + (regm & 0x0fu)], val); break; +#endif default: break; @@ -1222,231 +1406,62 @@ nuked_write_reg(void *priv, uint16_t reg, uint8_t val) } void -nuked_write_reg_buffered(void *priv, uint16_t reg, uint8_t val) +OPL3_WriteRegBuffered(void *priv, uint16_t reg, uint8_t val) { - nuked_t *dev = (nuked_t *) priv; - uint64_t time1; - uint64_t time2; + opl3_chip *chip = (opl3_chip *) priv; + uint64_t time1; + uint64_t time2; + opl3_writebuf *writebuf; + uint32_t writebuf_last; + + writebuf_last = chip->writebuf_last; + writebuf = &chip->writebuf[writebuf_last]; - if (dev->wrbuf[dev->wrbuf_last].reg & 0x0200) { - nuked_write_reg(dev, dev->wrbuf[dev->wrbuf_last].reg & 0x01ff, - dev->wrbuf[dev->wrbuf_last].data); + if (writebuf->reg & 0x0200) { + OPL3_WriteReg(chip, writebuf->reg & 0x01ff, writebuf->data); - dev->wrbuf_cur = (dev->wrbuf_last + 1) % WRBUF_SIZE; - dev->wrbuf_samplecnt = dev->wrbuf[dev->wrbuf_last].time; + chip->writebuf_cur = (writebuf_last + 1) % OPL_WRITEBUF_SIZE; + chip->writebuf_samplecnt = writebuf->time; } - dev->wrbuf[dev->wrbuf_last].reg = reg | 0x0200; - dev->wrbuf[dev->wrbuf_last].data = val; - time1 = dev->wrbuf_lasttime + WRBUF_DELAY; - time2 = dev->wrbuf_samplecnt; + writebuf->reg = reg | 0x0200; + writebuf->data = val; + time1 = chip->writebuf_lasttime + OPL_WRITEBUF_DELAY; + time2 = chip->writebuf_samplecnt; if (time1 < time2) time1 = time2; - dev->wrbuf[dev->wrbuf_last].time = time1; - dev->wrbuf_lasttime = time1; - dev->wrbuf_last = (dev->wrbuf_last + 1) % WRBUF_SIZE; -} - -void -nuked_generate(void *priv, int32_t *bufp) -{ - nuked_t *dev = (nuked_t *) priv; - int16_t accm; - int16_t shift = 0; - uint8_t i; - uint8_t j; - - bufp[1] = dev->mixbuff[1]; - - for (i = 0; i < 15; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); - } - - dev->mixbuff[0] = 0; - - for (i = 0; i < 18; i++) { - accm = 0; - - for (j = 0; j < 4; j++) - accm += *dev->chan[i].out[j]; - - dev->mixbuff[0] += (int16_t) (accm & dev->chan[i].cha); - } - for (i = 15; i < 18; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); - } - - bufp[0] = dev->mixbuff[0]; - - for (i = 18; i < 33; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); - } - - dev->mixbuff[1] = 0; - - for (i = 0; i < 18; i++) { - accm = 0; - - for (j = 0; j < 4; j++) - accm += *dev->chan[i].out[j]; - - dev->mixbuff[1] += (int16_t) (accm & dev->chan[i].chb); - } - - for (i = 33; i < 36; i++) { - slot_calc_fb(&dev->slot[i]); - env_calc(&dev->slot[i]); - phase_generate(&dev->slot[i]); - slot_generate(&dev->slot[i]); - } - - if ((dev->timer & 0x3f) == 0x3f) - dev->tremolopos = (dev->tremolopos + 1) % 210; - - if (dev->tremolopos < 105) - dev->tremolo = dev->tremolopos >> dev->tremoloshift; - else - dev->tremolo = (210 - dev->tremolopos) >> dev->tremoloshift; - - if ((dev->timer & 0x03ff) == 0x03ff) - dev->vibpos = (dev->vibpos + 1) & 7; - - dev->timer++; - dev->eg_add = 0; - - if (dev->eg_timer) { - while (shift < 36 && ((dev->eg_timer >> shift) & 1) == 0) - shift++; - - if (shift > 12) - dev->eg_add = 0; - else - dev->eg_add = shift + 1; - } - - if (dev->eg_timerrem || dev->eg_state) { - if (dev->eg_timer == 0xfffffffff) { - dev->eg_timer = 0; - dev->eg_timerrem = 1; - } else { - dev->eg_timer++; - dev->eg_timerrem = 0; - } - } - - dev->eg_state ^= 1; - - while (dev->wrbuf[dev->wrbuf_cur].time <= dev->wrbuf_samplecnt) { - if (!(dev->wrbuf[dev->wrbuf_cur].reg & 0x200)) - break; - - dev->wrbuf[dev->wrbuf_cur].reg &= 0x01ff; - - nuked_write_reg(dev, dev->wrbuf[dev->wrbuf_cur].reg, - dev->wrbuf[dev->wrbuf_cur].data); - - dev->wrbuf_cur = (dev->wrbuf_cur + 1) % WRBUF_SIZE; - } - - dev->wrbuf_samplecnt++; + writebuf->time = time1; + chip->writebuf_lasttime = time1; + chip->writebuf_last = (writebuf_last + 1) % OPL_WRITEBUF_SIZE; } void -nuked_generate_resampled(nuked_t *dev, int32_t *bufp) +OPL3_Generate4ChStream(opl3_chip *chip, int32_t *sndptr1, int32_t *sndptr2, uint32_t numsamples) { - while (dev->samplecnt >= dev->rateratio) { - dev->oldsamples[0] = dev->samples[0]; - dev->oldsamples[1] = dev->samples[1]; - nuked_generate(dev, dev->samples); - dev->samplecnt -= dev->rateratio; + int32_t samples[4]; + + for (uint_fast32_t i = 0; i < numsamples; i++) { + OPL3_Generate4Ch(chip, samples); + sndptr1[0] = samples[0]; + sndptr1[1] = samples[1]; + sndptr2[0] = samples[2]; + sndptr2[1] = samples[3]; + sndptr1 += 2; + sndptr2 += 2; } - - bufp[0] = (int32_t) ((dev->oldsamples[0] * (dev->rateratio - dev->samplecnt) - + dev->samples[0] * dev->samplecnt) - / dev->rateratio); - bufp[1] = (int32_t) ((dev->oldsamples[1] * (dev->rateratio - dev->samplecnt) - + dev->samples[1] * dev->samplecnt) - / dev->rateratio); - - dev->samplecnt += 1 << RSM_FRAC; } void -nuked_generate_raw(nuked_t *dev, int32_t *bufp) +OPL3_GenerateStream(opl3_chip *chip, int32_t *sndptr, uint32_t numsamples) { - nuked_generate(dev, dev->samples); - - bufp[0] = (int32_t) dev->samples[0]; - bufp[1] = (int32_t) dev->samples[1]; -} - -void -nuked_generate_stream(nuked_t *dev, int32_t *sndptr, uint32_t num) -{ - for (uint32_t i = 0; i < num; i++) { - nuked_generate_raw(dev, sndptr); + for (uint_fast32_t i = 0; i < numsamples; i++) { + OPL3_Generate(chip, sndptr); sndptr += 2; } } -void -nuked_init(nuked_t *dev, uint32_t samplerate) -{ - uint8_t i; - - memset(dev, 0x00, sizeof(nuked_t)); - - for (i = 0; i < 36; i++) { - dev->slot[i].dev = dev; - dev->slot[i].mod = &dev->zeromod; - dev->slot[i].eg_rout = 0x01ff; - dev->slot[i].eg_out = 0x01ff; - dev->slot[i].eg_gen = envelope_gen_num_release; - dev->slot[i].trem = (uint8_t *) &dev->zeromod; - dev->slot[i].slot_num = i; - } - - for (i = 0; i < 18; i++) { - dev->chan[i].slots[0] = &dev->slot[ch_slot[i]]; - dev->chan[i].slots[1] = &dev->slot[ch_slot[i] + 3]; - dev->slot[ch_slot[i]].chan = &dev->chan[i]; - dev->slot[ch_slot[i] + 3].chan = &dev->chan[i]; - - if ((i % 9) < 3) - dev->chan[i].pair = &dev->chan[i + 3]; - else if ((i % 9) < 6) - dev->chan[i].pair = &dev->chan[i - 3]; - - dev->chan[i].dev = dev; - dev->chan[i].out[0] = &dev->zeromod; - dev->chan[i].out[1] = &dev->zeromod; - dev->chan[i].out[2] = &dev->zeromod; - dev->chan[i].out[3] = &dev->zeromod; - dev->chan[i].chtype = ch_2op; - dev->chan[i].cha = 0xffff; - dev->chan[i].chb = 0xffff; - dev->chan[i].ch_num = i; - - channel_setup_alg(&dev->chan[i]); - } - - dev->noise = 1; - dev->rateratio = (samplerate << RSM_FRAC) / 49716; - dev->tremoloshift = 4; - dev->vibshift = 1; -} - static void nuked_timer_tick(nuked_drv_t *dev, int tmr) { @@ -1523,7 +1538,7 @@ nuked_drv_init(const device_t *info) dev->status = 0x06; /* Initialize the NukedOPL object. */ - nuked_init(&dev->opl, OPL_FREQ); + OPL3_Reset(&dev->opl, OPL_FREQ); timer_add(&dev->timers[0], nuked_timer_1, dev, 0); timer_add(&dev->timers[1], nuked_timer_2, dev, 0); @@ -1546,7 +1561,7 @@ nuked_drv_update(void *priv) if (dev->pos >= music_pos_global) return dev->buffer; - nuked_generate_stream(&dev->opl, + OPL3_GenerateStream(&dev->opl, &dev->buffer[dev->pos * 2], music_pos_global - dev->pos); @@ -1588,7 +1603,7 @@ nuked_drv_write(uint16_t port, uint8_t val, void *priv) nuked_drv_update(dev); if ((port & 0x0001) == 0x0001) { - nuked_write_reg_buffered(&dev->opl, dev->port, val); + OPL3_WriteRegBuffered(&dev->opl, dev->port, val); switch (dev->port) { case 0x002: /* Timer 1 */ @@ -1672,4 +1687,4 @@ const fm_drv_t nuked_opl_drv = { &nuked_drv_set_do_cycles, NULL, NULL, -}; \ No newline at end of file +}; diff --git a/src/sound/snd_opl_ymfm.cpp b/src/sound/snd_opl_ymfm.cpp index 1da97adfa2..ccd77ed395 100644 --- a/src/sound/snd_opl_ymfm.cpp +++ b/src/sound/snd_opl_ymfm.cpp @@ -425,7 +425,7 @@ const device_t ym3812_ymfm_device = { .init = ymfm_drv_init, .close = ymfm_drv_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -439,7 +439,7 @@ const device_t ymf262_ymfm_device = { .init = ymfm_drv_init, .close = ymfm_drv_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -453,7 +453,7 @@ const device_t ymf289b_ymfm_device = { .init = ymfm_drv_init, .close = ymfm_drv_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL @@ -467,7 +467,7 @@ const device_t ymf278b_ymfm_device = { .init = ymfm_drv_init, .close = ymfm_drv_close, .reset = NULL, - { .available = NULL }, + .available = NULL, .speed_changed = NULL, .force_redraw = NULL, .config = NULL diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index 243332257b..5ab14d1b83 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -823,7 +823,7 @@ pas16_in(uint16_t port, void *priv) - 2 = FM (1 = stereo, 0 = mono); - 3 = Code (1 = 16-bit, 0 = 8-bit). */ - ret = pas16->type ? pas16->type : 0x06; + ret = pas16->type ? pas16->type : 0x07; break; case 0xf000: @@ -1020,7 +1020,7 @@ pas16_nsc_mixer_reset(nsc_mixer_t *mixer) mixer->lmc1982_regs[LMC1982_REG_ISELECT] = 0x01; mixer->lmc1982_regs[LMC1982_REG_LES] = 0x00; mixer->lmc1982_regs[LMC1982_REG_BASS] = mixer->lmc1982_regs[LMC1982_REG_TREBLE] = 0x06; - mixer->lmc1982_regs[LMC1982_REG_VOL_L] = mixer->lmc1982_regs[LMC1982_REG_VOL_R] = 0x28; + mixer->lmc1982_regs[LMC1982_REG_VOL_L] = mixer->lmc1982_regs[LMC1982_REG_VOL_R] = 0x00; /*0x28*/ /*Note by TC1995: otherwise the volume gets lowered too much*/ mixer->lmc1982_regs[LMC1982_REG_MODE] = 0x05; lmc1982_recalc(mixer); @@ -1504,7 +1504,8 @@ pas16_out(uint16_t port, uint8_t val, void *priv) pas16->timeout_count = val; if (timer_is_enabled(&pas16->scsi_timer)) timer_disable(&pas16->scsi_timer); - timer_set_delay_u64(&pas16->scsi_timer, (val & 0x3f) * PASSCSICONST); + if ((val & 0x3f) > 0x00) + timer_set_delay_u64(&pas16->scsi_timer, (val & 0x3f) * PASSCSICONST); } break; diff --git a/src/sound/snd_resid.cc b/src/sound/snd_resid.cpp similarity index 62% rename from src/sound/snd_resid.cc rename to src/sound/snd_resid.cpp index 94bbcd5913..d7082e47e9 100644 --- a/src/sound/snd_resid.cc +++ b/src/sound/snd_resid.cpp @@ -9,9 +9,11 @@ #define RESID_FREQ 48000 +using reSIDfp::SID; + typedef struct psid_t { /* resid sid implementation */ - SIDFP *sid; + SID *sid; int16_t last_sample; } psid_t; @@ -23,42 +25,33 @@ sid_init(void) #if 0 psid_t *psid; #endif - sampling_method method = SAMPLE_INTERPOLATE; - float cycles_per_sec = 14318180.0 / 16.0; + reSIDfp::SamplingMethod method = reSIDfp::DECIMATE; + float cycles_per_sec = 14318180.0 / 16.0; psid = new psid_t; #if 0 - psid = (psid_t *)malloc(sizeof(sound_t)); + psid = (psid_t *) malloc(sizeof(sound_t)); #endif - psid->sid = new SIDFP; - - psid->sid->set_chip_model(MOS8580FP); + psid->sid = new SID; - psid->sid->set_voice_nonlinearity(1.0f); - psid->sid->get_filter().set_distortion_properties(0.f, 0.f, 0.f); - psid->sid->get_filter().set_type4_properties(6.55f, 20.0f); - - psid->sid->enable_filter(true); - psid->sid->enable_external_filter(true); + psid->sid->setChipModel(reSIDfp::MOS8580); + psid->sid->enableFilter(true); psid->sid->reset(); for (uint8_t c = 0; c < 32; c++) psid->sid->write(c, 0); - if (!psid->sid->set_sampling_parameters(cycles_per_sec, method, - (float) RESID_FREQ, 0.9 * (float) RESID_FREQ / 2.0)) { + try { + psid->sid->setSamplingParameters(cycles_per_sec, method, (float) RESID_FREQ, 0.9 * (float) RESID_FREQ / 2.0); + } catch (reSIDfp::SIDError) { #if 0 printf("reSID failed!\n"); #endif } - psid->sid->set_chip_model(MOS6581FP); - psid->sid->set_voice_nonlinearity(0.96f); - psid->sid->get_filter().set_distortion_properties(3.7e-3f, 2048.f, 1.2e-4f); - + psid->sid->setChipModel(reSIDfp::MOS6581); psid->sid->input(0); - psid->sid->get_filter().set_type3_properties(1.33e6f, 2.2e9f, 1.0056f, 7e3f); return (void *) psid; } @@ -117,7 +110,7 @@ static void fillbuf2(int &count, int16_t *buf, int len) { int c; - c = psid->sid->clock(count, buf, len, 1); + c = psid->sid->clock(count, buf); if (!c) *buf = psid->last_sample; psid->last_sample = *buf; diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 364c015578..4f6961fab4 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1374,6 +1374,70 @@ sb_ct1745_mixer_reset(sb_t *sb) } } +static void +ess_base_write(uint16_t addr, uint8_t val, void *priv) +{ + sb_t * ess = (sb_t *) priv; + + switch (addr & 0x000f) { + case 0x0002: + case 0x0003: + case 0x0006: + case 0x000c: + ess->dsp.activity &= 0xdf; + break; + case 0x0008: + case 0x0009: + ess->dsp.activity &= 0x7f; + break; + } +} + +static uint8_t +ess_base_read(uint16_t addr, void *priv) +{ + sb_t * ess = (sb_t *) priv; + + switch (addr & 0x000f) { + case 0x0002: + case 0x0003: + case 0x0004: /* Undocumented but tested by the LBA 2 ES688 driver. */ + case 0x000a: + ess->dsp.activity &= 0xdf; + break; + case 0x0008: + case 0x0009: + ess->dsp.activity &= 0x7f; + break; + case 0x000c: + case 0x000e: + ess->dsp.activity &= 0xbf; + break; + } + + sb_log("ess_base_read(%04X): %04X, activity now: %02X\n", addr, addr & 0x000f, ess->dsp.activity); + + return 0xff; +} + +static void +ess_fm_midi_write(uint16_t addr, uint8_t val, void *priv) +{ + sb_t * ess = (sb_t *) priv; + + ess->dsp.activity &= 0x7f; +} + +static uint8_t +ess_fm_midi_read(uint16_t addr, void *priv) +{ + sb_t * ess = (sb_t *) priv; + + ess->dsp.activity &= 0x7f; + + return 0xff; +} + void ess_mixer_write(uint16_t addr, uint8_t val, void *priv) { @@ -1500,6 +1564,12 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) { uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] << 1) & 0x30); sb_log("mpu401_base_addr = %04X\n", mpu401_base_addr); + + io_removehandler(ess->midi_addr, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200); if (ess->dsp.sb_subtype != SB_SUBTYPE_ESS_ES1688) { @@ -1515,11 +1585,12 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) ess->opl.priv); } } - switch ((mixer->regs[0x40] >> 5) & 0x7) { + if (ess->mpu != NULL) switch ((mixer->regs[0x40] >> 5) & 0x7) { default: break; case 0: - mpu401_change_addr(ess->mpu, 0x00); + mpu401_base_addr = 0x0000; + mpu401_change_addr(ess->mpu, mpu401_base_addr); mpu401_setirq(ess->mpu, -1); break; case 1: @@ -1551,6 +1622,11 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) mpu401_setirq(ess->mpu, 10); break; } + ess->midi_addr = mpu401_base_addr; + io_sethandler(addr, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); break; } @@ -2170,11 +2246,28 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_removehandler(addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_removehandler(addr + 4, 0x0002, ess_mixer_read, NULL, NULL, ess_mixer_write, NULL, NULL, ess); + io_removehandler(addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_removehandler(addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_removehandler(addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + ess->mixer_ess.ess_id_str[2] = 0x00; ess->mixer_ess.ess_id_str[3] = 0x00; @@ -2185,14 +2278,28 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_removehandler(addr, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); } - if (ess->pnp == 3) - mpu401_change_addr(ess->mpu, 0); + if (ess->pnp == 3) { + addr = ess->midi_addr; + if (addr) { + ess->midi_addr = 0; + if (ess->mpu != NULL) + mpu401_change_addr(ess->mpu, 0); + io_removehandler(addr, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + } + } sb_dsp_setaddr(&ess->dsp, 0); sb_dsp_setirq(&ess->dsp, 0); - if (ess->pnp == 3) + if ((ess->pnp == 3) && (ess->mpu != NULL)) mpu401_setirq(ess->mpu, -1); sb_dsp_setdma8(&ess->dsp, ISAPNP_DMA_DISABLED); sb_dsp_setdma16_8(&ess->dsp, ISAPNP_DMA_DISABLED); @@ -2208,12 +2315,28 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_sethandler(addr + 4, 0x0002, ess_mixer_read, NULL, NULL, ess_mixer_write, NULL, NULL, ess); sb_dsp_setaddr(&ess->dsp, addr); + io_sethandler(addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff; ess->mixer_ess.ess_id_str[3] = addr & 0xff; @@ -2226,18 +2349,28 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(addr, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); } if (ess->pnp == 3) { addr = config->io[2].base; - if (addr != ISAPNP_IO_DISABLED) - mpu401_change_addr(ess->mpu, addr); + if (addr != ISAPNP_IO_DISABLED) { + if (ess->mpu != NULL) + mpu401_change_addr(ess->mpu, addr); + io_sethandler(addr, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + } } val = config->irq[0].irq; if (val != ISAPNP_IRQ_DISABLED) { sb_dsp_setirq(&ess->dsp, val); - if (ess->pnp == 3) + if ((ess->pnp == 3) && (ess->mpu != NULL)) mpu401_setirq(ess->mpu, val); } @@ -2252,7 +2385,7 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co case 1: if (ess->pnp == 3) { /* Game */ gameport_remap(ess->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0); - } else { /* MPU-401 */ + } else if (ess->mpu != NULL) { /* MPU-401 */ mpu401_change_addr(ess->mpu, 0); mpu401_setirq(ess->mpu, -1); @@ -2316,23 +2449,50 @@ ess_soundpiper_mca_write(const int port, const uint8_t val, void *priv) ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_removehandler(ess->dsp.sb_addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_removehandler(0x0388, 0x0004, ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_removehandler(0x0388, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_removehandler(ess->dsp.sb_addr + 4, 0x0002, ess_mixer_read, NULL, NULL, ess_mixer_write, NULL, NULL, ess); + + io_removehandler(ess->dsp.sb_addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_removehandler(ess->dsp.sb_addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_removehandler(ess->dsp.sb_addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); } /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&ess->dsp, 0); gameport_remap(ess->gameport, 0); - if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) { mpu401_change_addr(ess->mpu, 0); + io_removehandler(0x0330, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + } + ess->pos_regs[port & 7] = val; if (ess->pos_regs[2] & 1) { @@ -2357,16 +2517,44 @@ ess_soundpiper_mca_write(const int port, const uint8_t val, void *priv) ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_sethandler(0x0388, 0x0004, ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(0x0388, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_sethandler(ess->dsp.sb_addr + 4, 0x0002, ess_mixer_read, NULL, NULL, ess_mixer_write, NULL, NULL, ess); - if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + io_sethandler(ess->dsp.sb_addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) { mpu401_change_addr(ess->mpu, ess->pos_regs[3] & 0x02 ? 0x0330 : 0); + + if (ess->pos_regs[3] & 0x02) + io_sethandler(0x0330, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + } } /* DSP I/O handler is activated in sb_dsp_setaddr */ @@ -2424,21 +2612,49 @@ ess_chipchat_mca_write(int port, uint8_t val, void *priv) ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_removehandler(ess->dsp.sb_addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_removehandler(0x0388, 0x0004, ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_removehandler(0x0388, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_removehandler(ess->dsp.sb_addr + 4, 0x0002, ess_mixer_read, NULL, NULL, ess_mixer_write, NULL, NULL, ess); + + io_removehandler(ess->dsp.sb_addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_removehandler(ess->dsp.sb_addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_removehandler(ess->dsp.sb_addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); } /* DSP I/O handler is activated in sb_dsp_setaddr */ sb_dsp_setaddr(&ess->dsp, 0); gameport_remap(ess->gameport, 0); - mpu401_change_addr(ess->mpu, 0); + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) { + mpu401_change_addr(ess->mpu, 0); + + io_removehandler(0x0330, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + } ess->pos_regs[port & 7] = val; @@ -2454,16 +2670,44 @@ ess_chipchat_mca_write(int port, uint8_t val, void *priv) ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); + io_sethandler(ess->dsp.sb_addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); io_sethandler(0x0388, 0x0004, ess->opl.read, NULL, NULL, ess->opl.write, NULL, NULL, ess->opl.priv); - io_sethandler(ess->dsp.sb_addr + 4, 0x0002, + io_sethandler(0x0388, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 4, 0x0004, ess_mixer_read, NULL, NULL, ess_mixer_write, NULL, NULL, ess); - if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) + io_sethandler(ess->dsp.sb_addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(ess->dsp.sb_addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + + if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) { mpu401_change_addr(ess->mpu, (ess->pos_regs[2] == 0x51) ? 0x0330 : 0); + + if (ess->pos_regs[2] == 0x51) + io_sethandler(0x0330, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + } } /* DSP I/O handler is activated in sb_dsp_setaddr */ @@ -2948,7 +3192,8 @@ sb_16_init(UNUSED(const device_t *info)) if (mpu_addr) { sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, + device_get_config_int("receive_input401")); } else sb->mpu = NULL; sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3292,7 +3537,8 @@ sb_awe32_init(UNUSED(const device_t *info)) if (mpu_addr) { sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), 0, M_UART, + device_get_config_int("receive_input401")); } else sb->mpu = NULL; sb_dsp_set_mpu(&sb->dsp, sb->mpu); @@ -3452,20 +3698,39 @@ ess_x688_init(UNUSED(const device_t *info)) ess_mixer_reset(ess); /* DSP I/O handler is activated in sb_dsp_setaddr */ - { - io_sethandler(addr, 0x0004, - ess->opl.read, NULL, NULL, - ess->opl.write, NULL, NULL, - ess->opl.priv); - io_sethandler(addr + 8, 0x0002, - ess->opl.read, NULL, NULL, - ess->opl.write, NULL, NULL, - ess->opl.priv); - io_sethandler(0x0388, 0x0004, - ess->opl.read, NULL, NULL, - ess->opl.write, NULL, NULL, - ess->opl.priv); - } + io_sethandler(addr, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(addr + 8, 0x0002, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(addr + 8, 0x0002, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + io_sethandler(0x0388, 0x0004, + ess->opl.read, NULL, NULL, + ess->opl.write, NULL, NULL, + ess->opl.priv); + io_sethandler(0x0388, 0x0004, + ess_fm_midi_read, NULL, NULL, + ess_fm_midi_write, NULL, NULL, + ess); + + io_sethandler(addr + 2, 0x0004, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(addr + 6, 0x0001, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); + io_sethandler(addr + 0x0a, 0x0006, + ess_base_read, NULL, NULL, + ess_base_write, NULL, NULL, + ess); ess->mixer_enabled = 1; ess->mixer_ess.regs[0x40] = 0x0a; @@ -3790,7 +4055,7 @@ static const device_config_t sb_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -3900,7 +4165,7 @@ static const device_config_t sb15_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4029,7 +4294,7 @@ static const device_config_t sb2_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4095,7 +4360,7 @@ static const device_config_t sb_mcv_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4185,7 +4450,7 @@ static const device_config_t sb_pro_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4196,7 +4461,7 @@ static const device_config_t sb_pro_config[] = { static const device_config_t sb_pro_mcv_config[] = { { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4349,7 +4614,7 @@ static const device_config_t sb_16_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4374,7 +4639,7 @@ static const device_config_t sb_16_pnp_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4431,7 +4696,7 @@ static const device_config_t sb_32_pnp_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4651,7 +4916,7 @@ static const device_config_t sb_awe32_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4708,7 +4973,7 @@ static const device_config_t sb_awe32_pnp_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4785,7 +5050,7 @@ static const device_config_t sb_awe64_value_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4858,7 +5123,7 @@ static const device_config_t sb_awe64_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -4923,7 +5188,7 @@ static const device_config_t sb_awe64_gold_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -5053,7 +5318,7 @@ static const device_config_t ess_688_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -5184,7 +5449,7 @@ static const device_config_t ess_1688_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -5203,7 +5468,7 @@ static const device_config_t ess_1688_config[] = { static const device_config_t ess_688_pnp_config[] = { { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 @@ -5222,7 +5487,7 @@ static const device_config_t ess_1688_pnp_config[] = { }, { .name = "receive_input", - .description = "Receive input (SB MIDI)", + .description = "Receive input (DSP MIDI)", .type = CONFIG_BINARY, .default_string = "", .default_int = 1 diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 65f33f4a3d..4cfd2c7bbe 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -442,15 +442,51 @@ sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *mpu) { dsp->mpu = mpu; - if (mpu != NULL) + if (IS_NOT_ESS(dsp) && (mpu != NULL)) mpu401_irq_attach(mpu, sb_dsp_irq_update, sb_dsp_irq_pending, dsp); } +static void +sb_stop_dma(const sb_dsp_t *dsp) +{ + dma_set_drq(dsp->sb_8_dmanum, 0); + + if (dsp->sb_16_dmanum != 0xff) { + if (dsp->sb_16_dmanum == 4) + dma_set_drq(dsp->sb_8_dmanum, 0); + else + dma_set_drq(dsp->sb_16_dmanum, 0); + } + + if (dsp->sb_16_8_dmanum != 0xff) + dma_set_drq(dsp->sb_16_8_dmanum, 0); +} + +static void +sb_finish_dma(sb_dsp_t *dsp) +{ + if (dsp->ess_playback_mode) { + ESSreg(0xB8) &= ~0x01; + dma_set_drq(dsp->sb_8_dmanum, 0); + } else + sb_stop_dma(dsp); +} + void sb_dsp_reset(sb_dsp_t *dsp) { midi_clear_buffer(); + if (dsp->sb_8_enable) { + dsp->sb_8_enable = 0; + sb_finish_dma(dsp); + } + + if (dsp->sb_16_enable) { + dsp->sb_16_enable = 0; + sb_finish_dma(dsp); + } + timer_disable(&dsp->output_timer); timer_disable(&dsp->input_timer); @@ -553,26 +589,18 @@ sb_resume_dma(const sb_dsp_t *dsp, const int is_8) } else if (is_8) dma_set_drq(dsp->sb_8_dmanum, 1); else { - if (dsp->sb_16_dmanum != 0xff) - dma_set_drq(dsp->sb_16_dmanum, 1); + if (dsp->sb_16_dmanum != 0xff) { + if (dsp->sb_16_dmanum == 4) + dma_set_drq(dsp->sb_8_dmanum, 1); + else + dma_set_drq(dsp->sb_16_dmanum, 1); + } if (dsp->sb_16_8_dmanum != 0xff) dma_set_drq(dsp->sb_16_8_dmanum, 1); } } -static void -sb_stop_dma(const sb_dsp_t *dsp) -{ - dma_set_drq(dsp->sb_8_dmanum, 0); - - if (dsp->sb_16_dmanum != 0xff) - dma_set_drq(dsp->sb_16_dmanum, 0); - - if (dsp->sb_16_8_dmanum != 0xff) - dma_set_drq(dsp->sb_16_8_dmanum, 0); -} - void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) { @@ -609,9 +637,12 @@ sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) if (!timer_is_enabled(&dsp->output_timer)) timer_set_delay_u64(&dsp->output_timer, (uint64_t) dsp->sblatcho); - if (dsp->sb_16_dma_supported) - dma_set_drq(dsp->sb_16_dmanum, 1); - else + if (dsp->sb_16_dma_supported) { + if (dsp->sb_16_dmanum == 4) + dma_set_drq(dsp->sb_8_dmanum, 1); + else + dma_set_drq(dsp->sb_16_dmanum, 1); + } else dma_set_drq(dsp->sb_16_8_dmanum, 1); } @@ -649,9 +680,12 @@ sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len) if (!timer_is_enabled(&dsp->input_timer)) timer_set_delay_u64(&dsp->input_timer, (uint64_t) dsp->sblatchi); - if (dsp->sb_16_dma_supported) - dma_set_drq(dsp->sb_16_dmanum, 1); - else + if (dsp->sb_16_dma_supported) { + if (dsp->sb_16_dmanum == 4) + dma_set_drq(dsp->sb_8_dmanum, 1); + else + dma_set_drq(dsp->sb_16_dmanum, 1); + } else dma_set_drq(dsp->sb_16_8_dmanum, 1); } @@ -712,6 +746,8 @@ sb_8_read_dma(void *priv) sb_dsp_t *dsp = (sb_dsp_t *) priv; int ret; + dsp->activity &= 0xdf; + if (dsp->sb_8_dmanum >= 4) { if (dsp->dma_ff) { uint32_t temp = (dsp->dma_data & 0xff00) >> 8; @@ -736,7 +772,9 @@ sb_8_read_dma(void *priv) int sb_8_write_dma(void *priv, uint8_t val) { - const sb_dsp_t *dsp = (sb_dsp_t *) priv; + sb_dsp_t *dsp = (sb_dsp_t *) priv; + + dsp->activity &= 0xdf; return dma_channel_write(dsp->sb_8_dmanum, val) == DMA_NODATA; } @@ -756,18 +794,23 @@ sb_8_write_dma(void *priv, uint8_t val) int sb_16_read_dma(void *priv) { - const sb_dsp_t *dsp = (sb_dsp_t *) priv; + sb_dsp_t *dsp = (sb_dsp_t *) priv; int ret; int dma_ch = dsp->sb_16_dmanum; - if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate) + dsp->activity &= 0xdf; + + if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate && (dma_ch != 4)) ret = dma_channel_read(dma_ch); else { if (dsp->sb_16_dma_enabled) { /* High DMA channel enabled, either translation is enabled or 16-bit transfers are not supported. */ - dma_ch = dsp->sb_16_8_dmanum; + if (dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate && (dma_ch == 4)) + dma_ch = dsp->sb_8_dmanum; + else + dma_ch = dsp->sb_16_8_dmanum; } else /* High DMA channel disabled, always use the first 8-bit channel. */ dma_ch = dsp->sb_8_dmanum; @@ -791,17 +834,22 @@ sb_16_read_dma(void *priv) int sb_16_write_dma(void *priv, uint16_t val) { - const sb_dsp_t *dsp = (sb_dsp_t *) priv; + sb_dsp_t *dsp = (sb_dsp_t *) priv; int dma_ch = dsp->sb_16_dmanum; int ret; - if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate) + dsp->activity &= 0xdf; + + if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate && (dma_ch != 4)) ret = dma_channel_write(dma_ch, val) == DMA_NODATA; else { if (dsp->sb_16_dma_enabled) { /* High DMA channel enabled, either translation is enabled or 16-bit transfers are not supported. */ - dma_ch = dsp->sb_16_8_dmanum; + if (dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate && (dma_ch == 4)) + dma_ch = dsp->sb_8_dmanum; + else + dma_ch = dsp->sb_16_8_dmanum; } else /* High DMA channel disabled, always use the first 8-bit channel. */ dma_ch = dsp->sb_8_dmanum; @@ -1702,19 +1750,15 @@ sb_exec_command(sb_dsp_t *dsp) sb_add_data(dsp, dsp->sb_test); break; case 0xF2: /* Trigger 8-bit IRQ */ - sb_dsp_log("Trigger IRQ\n"); - if (IS_ESS(dsp)) { - if (!timer_is_enabled(&dsp->irq_timer)) { - timer_set_delay_u64(&dsp->irq_timer, (100ULL * TIMER_USEC)); - } - } else { - sb_irq(dsp, 1); - dsp->ess_irq_generic = true; - } + sb_dsp_log("Trigger 8-bit IRQ\n"); + timer_set_delay_u64(&dsp->irq_timer, (10ULL * TIMER_USEC)); break; case 0xF3: /* Trigger 16-bit IRQ */ - sb_dsp_log("Trigger IRQ\n"); - dsp->ess_irq_generic = true; + sb_dsp_log("Trigger 16-bit IRQ\n"); + if (IS_ESS(dsp)) + dsp->ess_irq_generic = true; + else + timer_set_delay_u64(&dsp->irq16_timer, (10ULL * TIMER_USEC)); break; case 0xF8: if (dsp->sb_type < SB16) @@ -1867,7 +1911,11 @@ sb_read(uint16_t a, void *priv) switch (a & 0xf) { case 0x6: - ret = IS_ESS(dsp) ? 0x00 : 0xff; + if (IS_ESS(dsp)) { + ret = (dsp->espcm_fifo_reset & 0x03) | 0x08 | (dsp->activity & 0xe0); + dsp->activity |= 0xe0; + } else + ret = 0xff; break; case 0xA: /* Read data */ if (dsp->mpu && dsp->uart_midi) @@ -1886,6 +1934,10 @@ sb_read(uint16_t a, void *priv) dsp->state = DSP_S_NORMAL; break; case 0xC: /* Write data ready */ + /* Advance the state just in case something reads from here + without reading the status first. */ + if (dsp->state == DSP_S_RESET_WAIT) + dsp->state = DSP_S_NORMAL; if ((dsp->state == DSP_S_NORMAL) || IS_ESS(dsp)) { if (dsp->sb_8_enable || dsp->sb_type >= SB16) dsp->busy_count = (dsp->busy_count + 1) & 3; @@ -1927,7 +1979,9 @@ sb_read(uint16_t a, void *priv) else ret = 0x7f; } - } else + } else if (IS_AZTECH(dsp)) + ret = 0x00; + else ret = 0xff; break; case 0xE: /* Read data ready */ @@ -1949,10 +2003,8 @@ sb_read(uint16_t a, void *priv) else ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff; } - if (dsp->state == DSP_S_RESET_WAIT) { - ret &= 0x7f; + if (dsp->state == DSP_S_RESET_WAIT) dsp->state = DSP_S_NORMAL; - } break; case 0xF: /* 16-bit ack */ if (IS_NOT_ESS(dsp)) { @@ -2037,12 +2089,22 @@ sb_dsp_irq_poll(void *priv) dsp->ess_irq_generic = true; } +void +sb_dsp_irq16_poll(void *priv) +{ + sb_dsp_t *dsp = (sb_dsp_t *) priv; + + sb_irq(dsp, 0); + dsp->ess_irq_generic = true; +} + void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) { dsp->sb_type = type; dsp->sb_subtype = subtype; dsp->parent = parent; + dsp->activity = 0xe0; /* Default values. Use sb_dsp_setxxx() methods to change. */ dsp->sb_irqnum = 7; @@ -2071,15 +2133,18 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent) timer_add(&dsp->input_timer, sb_poll_i, dsp, 0); timer_add(&dsp->wb_timer, NULL, dsp, 0); timer_add(&dsp->irq_timer, sb_dsp_irq_poll, dsp, 0); + timer_add(&dsp->irq16_timer, sb_dsp_irq16_poll, dsp, 0); if (IS_ESS(dsp)) /* Initialize ESS filter to 8 kHz. This will be recalculated when a set frequency command is sent. */ recalc_sb16_filter(0, 8000 * 2); - else + else { + timer_add(&dsp->irq16_timer, sb_dsp_irq16_poll, dsp, 0); /* Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when a set frequency command is sent. */ recalc_sb16_filter(0, 3200 * 2); + } if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2)) { /* OPL3 or dual OPL2 is stereo. */ if (dsp->sb_has_real_opl) @@ -2161,16 +2226,6 @@ sb_dsp_dma_attach(sb_dsp_t *dsp, dsp->dma_priv = priv; } -static void -sb_finish_dma(sb_dsp_t *dsp) -{ - if (dsp->ess_playback_mode) { - ESSreg(0xB8) &= ~0x01; - dma_set_drq(dsp->sb_8_dmanum, 0); - } else - sb_stop_dma(dsp); -} - void sb_espcm_fifoctl_run(sb_dsp_t *dsp) { diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 519219934f..32f81c596a 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -21,7 +21,15 @@ static float volslog[16] = { 7.51785f, 9.46440f, 11.9194f, 15.0000f }; -void +static int +sn76489_check_tap_2(sn76489_t *sn76489) +{ + int ret = ((sn76489->shift >> sn76489->white_noise_tap_2) & 1); + + return (sn76489->type == SN76496) ? ret : !ret; +} + +static void sn76489_update(sn76489_t *sn76489) { for (; sn76489->pos < sound_pos_global; sn76489->pos++) { @@ -42,24 +50,28 @@ sn76489_update(sn76489_t *sn76489) result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2); sn76489->count[0] -= (512 * sn76489->psgconst); - while (sn76489->count[0] < 0 && sn76489->latch[0]) { + while ((sn76489->count[0] < 0) && sn76489->latch[0]) { sn76489->count[0] += (sn76489->latch[0] * 4); if (!(sn76489->noise & 4)) { - if (sn76489->shift & 1) - sn76489->shift |= 0x8000; - sn76489->shift >>= 1; + if ((sn76489->shift >> sn76489->white_noise_tap_1) & 1) { + sn76489->shift >>= 1; + sn76489->shift |= sn76489->feedback_mask; + } else + sn76489->shift >>= 1; } else { - if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1)) - sn76489->shift |= 0x8000; - sn76489->shift >>= 1; + if (((sn76489->shift >> sn76489->white_noise_tap_1) & 1) ^ sn76489_check_tap_2(sn76489)) { + sn76489->shift >>= 1; + sn76489->shift |= sn76489->feedback_mask; + } else + sn76489->shift >>= 1; } } - sn76489->buffer[sn76489->pos] = result; + sn76489->buffer[sn76489->pos] = (sn76489->type == NCR8496) ? -result : result; } } -void +static void sn76489_get_buffer(int32_t *buffer, int len, void *priv) { sn76489_t *sn76489 = (sn76489_t *) priv; @@ -74,7 +86,7 @@ sn76489_get_buffer(int32_t *buffer, int len, void *priv) sn76489->pos = 0; } -void +static void sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) { sn76489_t *sn76489 = (sn76489_t *) priv; @@ -88,7 +100,7 @@ sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) case 0: sn76489->freqlo[3] = data & 0xf; sn76489->latch[3] = (sn76489->freqlo[3] | (sn76489->freqhi[3] << 4)) << 6; - if (sn76489->extra_divide) + if (!sn76489->extra_divide) sn76489->latch[3] &= 0x3ff; if (!sn76489->latch[3]) sn76489->latch[3] = (sn76489->extra_divide ? 2048 : 1024) << 6; @@ -101,7 +113,7 @@ sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) case 0x20: sn76489->freqlo[2] = data & 0xf; sn76489->latch[2] = (sn76489->freqlo[2] | (sn76489->freqhi[2] << 4)) << 6; - if (sn76489->extra_divide) + if (!sn76489->extra_divide) sn76489->latch[2] &= 0x3ff; if (!sn76489->latch[2]) sn76489->latch[2] = (sn76489->extra_divide ? 2048 : 1024) << 6; @@ -114,7 +126,7 @@ sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) case 0x40: sn76489->freqlo[1] = data & 0xf; sn76489->latch[1] = (sn76489->freqlo[1] | (sn76489->freqhi[1] << 4)) << 6; - if (sn76489->extra_divide) + if (!sn76489->extra_divide) sn76489->latch[1] &= 0x3ff; if (!sn76489->latch[1]) sn76489->latch[1] = (sn76489->extra_divide ? 2048 : 1024) << 6; @@ -125,15 +137,13 @@ sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) sn76489->vol[1] = 0xf - data; break; case 0x60: - if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496) - sn76489->shift = 0x4000; + if (((data & 4) != (sn76489->noise & 4)) || (sn76489->type == SN76496)) + sn76489->shift = sn76489->feedback_mask; sn76489->noise = data & 0xf; if ((data & 3) == 3) sn76489->latch[0] = sn76489->latch[1]; else sn76489->latch[0] = 0x400 << (data & 3); - if (sn76489->extra_divide) - sn76489->latch[0] &= 0x3ff; if (!sn76489->latch[0]) sn76489->latch[0] = (sn76489->extra_divide ? 2048 : 1024) << 6; break; @@ -146,20 +156,25 @@ sn76489_write(UNUSED(uint16_t addr), uint8_t data, void *priv) break; } } else { + /* NCR8496 ignores writes to registers 1, 3, 5, 6 and 7 with bit 7 clear. */ + if ((sn76489->type != SN76496) && ((sn76489->firstdat & 0x10) || ((sn76489->firstdat & 0x70) == 0x60))) + return; + if ((sn76489->firstdat & 0x70) == 0x60 && (sn76489->type == SN76496)) { - if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496) - sn76489->shift = 0x4000; + if (sn76489->type == SN76496) + sn76489->shift = sn76489->feedback_mask; sn76489->noise = data & 0xf; if ((data & 3) == 3) sn76489->latch[0] = sn76489->latch[1]; else sn76489->latch[0] = 0x400 << (data & 3); if (!sn76489->latch[0]) - sn76489->latch[0] = 1024 << 6; + sn76489->latch[0] = (sn76489->extra_divide ? 2048 : 1024) << 6; } else if ((sn76489->firstdat & 0x70) != 0x60) { sn76489->freqhi[sn76489->lasttone] = data & 0x7F; - freq = sn76489->freqlo[sn76489->lasttone] | (sn76489->freqhi[sn76489->lasttone] << 4); - if (sn76489->extra_divide) + freq = sn76489->freqlo[sn76489->lasttone] | + (sn76489->freqhi[sn76489->lasttone] << 4); + if (!sn76489->extra_divide) freq &= 0x3ff; if (!freq) freq = sn76489->extra_divide ? 2048 : 1024; @@ -181,6 +196,16 @@ sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int fre { sound_add_handler(sn76489_get_buffer, sn76489); + if (type == SN76496) { + sn76489->white_noise_tap_1 = 0; + sn76489->white_noise_tap_2 = 1; + sn76489->feedback_mask = 0x4000; + } else { + sn76489->white_noise_tap_1 = 1; + sn76489->white_noise_tap_2 = 5; + sn76489->feedback_mask = 0x8000; + } + sn76489->latch[0] = sn76489->latch[1] = sn76489->latch[2] = sn76489->latch[3] = 0x3FF << 6; sn76489->vol[0] = 0; sn76489->vol[1] = sn76489->vol[2] = sn76489->vol[3] = 8; @@ -191,7 +216,7 @@ sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int fre sn76489->count[2] = (rand() & 0x3FF) << 6; sn76489->count[3] = (rand() & 0x3FF) << 6; sn76489->noise = 3; - sn76489->shift = 0x4000; + sn76489->shift = sn76489->feedback_mask; sn76489->type = type; sn76489->psgconst = (((double) freq / 64.0) / (double) FREQ_48000); diff --git a/src/sound/sound.c b/src/sound/sound.c index f527cbc61e..254e529ca4 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -96,38 +96,10 @@ static void *filter_cd_audio_p = NULL; void (*filter_pc_speaker)(int channel, double *buffer, void *priv) = NULL; void *filter_pc_speaker_p = NULL; -static const device_t sound_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -static const device_t sound_internal_device = { - .name = "Internal", - .internal_name = "internal", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const SOUND_CARD sound_cards[] = { // clang-format off - { &sound_none_device }, - { &sound_internal_device }, + { &device_none }, + { &device_internal }, { &acermagic_s20_device }, { &mirosound_pcm10_device }, { &adlib_device }, @@ -137,6 +109,11 @@ static const SOUND_CARD sound_cards[] = { { &cms_device }, { &cs4235_device }, { &cs4236b_device }, + { &ess_688_device }, + { &ess_ess0100_pnp_device }, + { &ess_1688_device }, + { &ess_ess0102_pnp_device }, + { &ess_ess0968_pnp_device }, { &gus_device }, { &sb_1_device }, { &sb_15_device }, @@ -172,13 +149,10 @@ static const SOUND_CARD sound_cards[] = { { &cmi8338_device }, { &cmi8738_device }, { &es1371_device }, + { &es1373_device }, + { &ct5880_device }, { &ad1881_device }, { &cs4297a_device }, - { &ess_688_device }, - { &ess_ess0100_pnp_device }, - { &ess_1688_device }, - { &ess_ess0102_pnp_device }, - { &ess_ess0968_pnp_device }, { NULL } // clang-format on }; @@ -247,14 +221,9 @@ sound_card_get_from_internal_name(const char *s) void sound_card_init(void) { - if ((sound_card_current[0] > SOUND_INTERNAL) && (sound_cards[sound_card_current[0]].device)) - device_add_inst(sound_cards[sound_card_current[0]].device, 1); - if ((sound_card_current[1] > SOUND_INTERNAL) && (sound_cards[sound_card_current[1]].device)) - device_add_inst(sound_cards[sound_card_current[1]].device, 2); - if ((sound_card_current[2] > SOUND_INTERNAL) && (sound_cards[sound_card_current[2]].device)) - device_add_inst(sound_cards[sound_card_current[2]].device, 3); - if ((sound_card_current[3] > SOUND_INTERNAL) && (sound_cards[sound_card_current[3]].device)) - device_add_inst(sound_cards[sound_card_current[3]].device, 4); + for (uint8_t i = 0; i < SOUND_CARD_MAX; i++) + if ((sound_card_current[i] > SOUND_INTERNAL) && (sound_cards[sound_card_current[i]].device)) + device_add_inst(sound_cards[sound_card_current[i]].device, i + 1); } void diff --git a/src/sound/ymfm/ymfm.h b/src/sound/ymfm/ymfm.h index 4f8ba1243c..c5986d66b7 100644 --- a/src/sound/ymfm/ymfm.h +++ b/src/sound/ymfm/ymfm.h @@ -485,6 +485,8 @@ class ymfm_saved_state class ymfm_engine_callbacks { public: + virtual ~ymfm_engine_callbacks() = default; + // timer callback; called by the interface when a timer fires virtual void engine_timer_expired(uint32_t tnum) = 0; @@ -506,6 +508,7 @@ class ymfm_interface template friend class fm_engine_base; public: + virtual ~ymfm_interface() = default; // the following functions must be implemented by any derived classes; the // default implementations are sufficient for some minimal operation, but will // likely need to be overridden to integrate with the outside world; they are diff --git a/src/sound/ymfm/ymfm_fm.ipp b/src/sound/ymfm/ymfm_fm.ipp index 55cdd643dc..a3ee8d3332 100644 --- a/src/sound/ymfm/ymfm_fm.ipp +++ b/src/sound/ymfm/ymfm_fm.ipp @@ -1518,7 +1518,7 @@ void fm_engine_base::engine_timer_expired(uint32_t tnum) for (uint32_t chnum = 0; chnum < CHANNELS; chnum++) if (bitfield(RegisterType::CSM_TRIGGER_MASK, chnum)) { - m_channel[chnum]->keyonoff(1, KEYON_CSM, chnum); + m_channel[chnum]->keyonoff(0xf, KEYON_CSM, chnum); m_modified_channels |= 1 << chnum; } diff --git a/src/sound/ymfm/ymfm_ssg.h b/src/sound/ymfm/ymfm_ssg.h index 749ad146fe..cb7ec9e7c4 100644 --- a/src/sound/ymfm/ymfm_ssg.h +++ b/src/sound/ymfm/ymfm_ssg.h @@ -49,6 +49,8 @@ namespace ymfm class ssg_override { public: + virtual ~ssg_override() = default; + // reset our status virtual void ssg_reset() = 0; diff --git a/src/timer.c b/src/timer.c index d7102ffc3c..6ddf8ebb51 100644 --- a/src/timer.c +++ b/src/timer.c @@ -253,3 +253,31 @@ timer_on_auto(pc_timer_t *timer, double period) else timer_stop(timer); } + +void +timer_set_new_tsc(uint64_t new_tsc) +{ + pc_timer_t *timer = NULL; + /* Run timers already expired. */ +#ifdef USE_DYNAREC + if (cpu_use_dynarec) + update_tsc(); +#endif + + if (!timer_head) { + tsc = new_tsc; + return; + } + + timer = timer_head; + timer_target = new_tsc + (int32_t)(timer_get_ts_int(timer_head) - (uint32_t)tsc); + + while (timer) { + int32_t offset_from_current_tsc = (int32_t)(timer_get_ts_int(timer) - (uint32_t)tsc); + timer->ts.ts32.integer = new_tsc + offset_from_current_tsc; + + timer = timer->next; + } + + tsc = new_tsc; +} diff --git a/src/unix/CMakeLists.txt b/src/unix/CMakeLists.txt index 4cbda5c831..91fa25f397 100644 --- a/src/unix/CMakeLists.txt +++ b/src/unix/CMakeLists.txt @@ -10,14 +10,19 @@ # # Authors: Cacodemon345 # David Hrdlička, +# Jasmine Iwanek, # # Copyright 2021 Cacodemon345. # Copyright 2021 David Hrdlička. # Copyright 2021 Andreas J. Reichel. -# Copyright 2021-2022 Jasmine Iwanek. +# Copyright 2021-2024 Jasmine Iwanek. # -add_library(plat OBJECT unix.c unix_serial_passthrough.c unix_netsocket.c) +add_library(plat OBJECT + unix.c + unix_serial_passthrough.c + unix_netsocket.c +) if (NOT CPPTHREADS) target_sources(plat PRIVATE unix_thread.c) @@ -27,7 +32,11 @@ set(THREADS_PREFER_PTHREAD_FLAG TRUE) find_package(Threads REQUIRED) target_link_libraries(86Box Threads::Threads) -add_library(ui OBJECT unix_sdl.c unix_cdrom.c dummy_cdrom_ioctl.c) +add_library(ui OBJECT + unix_sdl.c + unix_cdrom.c + dummy_cdrom_ioctl.c +) target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64) target_link_libraries(ui ${CMAKE_DL_LIBS}) diff --git a/src/unix/assets/86Box.spec b/src/unix/assets/86Box.spec index fdd7bbf55b..e351c017a2 100644 --- a/src/unix/assets/86Box.spec +++ b/src/unix/assets/86Box.spec @@ -15,7 +15,7 @@ %global romver 4.1 Name: 86Box -Version: 4.2 +Version: 4.2.2 Release: 1%{?dist} Summary: Classic PC emulator License: GPLv2+ @@ -121,5 +121,5 @@ popd %{_datadir}/%{name}/roms %changelog -* Sat Mar 23 2024 Robert de Rooy 4.2-1 +* Sat Aug 31 Jasmine Iwanek 4.2.2-1 - Bump release diff --git a/src/unix/assets/net.86box.86Box.metainfo.xml b/src/unix/assets/net.86box.86Box.metainfo.xml index 18df497033..47a0a6b87a 100644 --- a/src/unix/assets/net.86box.86Box.metainfo.xml +++ b/src/unix/assets/net.86box.86Box.metainfo.xml @@ -11,7 +11,7 @@ net.86box.86Box.desktop - + diff --git a/src/unix/dummy_cdrom_ioctl.c b/src/unix/dummy_cdrom_ioctl.c index cb08246756..ed19dfb1fc 100644 --- a/src/unix/dummy_cdrom_ioctl.c +++ b/src/unix/dummy_cdrom_ioctl.c @@ -167,8 +167,6 @@ plat_cdrom_get_audio_track_info(UNUSED(int end), int track, int *track_num, TMSF int plat_cdrom_get_audio_sub(UNUSED(uint32_t sector), uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) { - long size = 0; - *track = 1; *attr = 0x14; *index = 1; @@ -197,10 +195,6 @@ plat_cdrom_get_sector_size(UNUSED(uint32_t sector)) int plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) { - int status; - long size = 0; - int buflen = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; - plat_cdrom_open(); if (raw) { @@ -211,7 +205,7 @@ plat_cdrom_read_sector(uint8_t *buffer, int raw, uint32_t sector) /* Cooked */ } plat_cdrom_close(); - dummy_cdrom_ioctl_log("ReadSector status=%d, sector=%d, size=%" PRId64 ".\n", status, sector, (long long) size); + dummy_cdrom_ioctl_log("ReadSector sector=%d.\n", sector); return 0; } diff --git a/src/unix/unix.c b/src/unix/unix.c index 58cb1448f2..d4d73817f9 100644 --- a/src/unix/unix.c +++ b/src/unix/unix.c @@ -266,6 +266,10 @@ plat_get_string(int i) return L"Make sure libpcap is installed and that you are on a libpcap-compatible network connection."; case STRING_GHOSTSCRIPT_ERROR_TITLE: return L"Unable to initialize Ghostscript"; + case STRING_GHOSTPCL_ERROR_TITLE: + return L"Unable to initialize GhostPCL"; + case STRING_GHOSTPCL_ERROR_DESC: + return L"libgpcl6 is required for automatic conversion of PCL files to PDF.\n\nAny documents sent to the generic PCL printer will be saved as Printer Command Language (.pcl) files."; case STRING_HW_NOT_AVAILABLE_MACHINE: return L"Machine \"%hs\" is not available due to missing ROMs in the roms/machines directory. Switching to an available machine."; case STRING_HW_NOT_AVAILABLE_VIDEO: @@ -636,8 +640,12 @@ ui_msgbox_header(int flags, void *header, void *message) SDL_MessageBoxData msgdata; SDL_MessageBoxButtonData msgbtn; - if (!header) - header = (void *) ((flags & MBX_ANSI) ? "86Box" : L"86Box"); + if (!header) { + if (flags & MBX_ANSI) + header = (void *) "86Box"; + else + header = (void *) L"86Box"; + } msgbtn.buttonid = 1; msgbtn.text = "OK"; @@ -1164,7 +1172,7 @@ monitor_thread(void *param) #endif } -extern int gfxcard[2]; +extern int gfxcard[GFXCARD_MAX]; int main(int argc, char **argv) { @@ -1182,7 +1190,8 @@ main(int argc, char **argv) return 6; } - gfxcard[1] = 0; + for (uint8_t i = 1; i < GFXCARD_MAX; i++) + gfxcard[i] = 0; eventthread = SDL_ThreadID(); blitmtx = SDL_CreateMutex(); if (!blitmtx) { diff --git a/src/unix/unix_sdl.c b/src/unix/unix_sdl.c index c7cc898be4..002e33fd69 100644 --- a/src/unix/unix_sdl.c +++ b/src/unix/unix_sdl.c @@ -392,7 +392,7 @@ sdl_reload(void) } int -plat_vidapi(char *api) +plat_vidapi(UNUSED(const char *api)) { return 0; } diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index c8fb7021d2..2f7607ad62 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -29,6 +29,10 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c vid_tvp3026_ramdac.c vid_att2xc498_ramdac.c vid_xga.c vid_bochs_vbe.c) +if(G100) + target_compile_definitions(vid PRIVATE USE_G100) +endif() + if(XL24) target_compile_definitions(vid PRIVATE USE_XL24) endif() diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index ff14701649..944a14a882 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -469,7 +469,7 @@ ibm8514_accel_out_pixtrans(svga_t *svga, UNUSED(uint16_t port), uint32_t val, in } } -static void +void ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; @@ -500,8 +500,9 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x86e9: case 0xc6e9: - if (len == 1) + if (len == 1) { dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); + } break; case 0x8ae8: @@ -548,6 +549,7 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) if (len != 1) dev->test = val; fallthrough; + case 0xd2e8: if (len == 1) dev->accel.err_term = (dev->accel.err_term & 0x3f00) | val; @@ -577,9 +579,8 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) break; case 0x96e9: case 0xd6e9: - if (len == 1) { + if (len == 1) dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0xff) | ((val & 0x07) << 8); - } break; case 0x9ae8: @@ -624,7 +625,6 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) dev->accel.cy = dev->accel.cur_y; if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; @@ -646,9 +646,9 @@ ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) dev->accel.cy = dev->accel.cur_y; if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; + if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); @@ -883,7 +883,7 @@ ibm8514_io_set(svga_t *svga) io_sethandler(0xfee8, 0x0002, ibm8514_accel_inb, ibm8514_accel_inw, NULL, ibm8514_accel_outb, ibm8514_accel_outw, NULL, svga); } -static void +void ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) { ibm8514_t *dev = (ibm8514_t *) svga->dev8514; @@ -894,88 +894,89 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) else { switch (port) { case 0x2e8: - case 0x2e9: + case 0x6e9: WRITE8(port, dev->htotal, val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): htotal=0x%02x.\n", port, val); + svga_recalctimings(svga); break; case 0x6e8: - case 0x6e9: - if (!(port & 1)) { - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { - dev->hdisped = val; - dev->hdisp = (dev->hdisped + 1) << 3; - } + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1]) { + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; } - ibm8514_log("IBM 8514/A: H_DISP write 06E8 = %d, advfunc=%x.\n", dev->hdisp, dev->accel.advfunc_cntl & 4); + ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); + svga_recalctimings(svga); break; case 0xae8: - case 0xae9: - if (!(port & 1)) { - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { - dev->hsync_start = val; - dev->hblankstart = (dev->hsync_start & 0x07); - } - } - ibm8514_log("IBM 8514/A: H_SYNC_STRT write 0AE8 = %d\n", val + 1); + dev->hsync_start = val; + ibm8514_log("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_start=%d.\n", port, val, (val + 1) << 3); + svga_recalctimings(svga); break; case 0xee8: - case 0xee9: - if (!(port & 1)) { - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { - dev->hsync_width = val; - dev->hblank_end_val = (dev->hblankstart + (dev->hsync_width & 0x1f) - 1) & 0x3f; - } - } - ibm8514_log("IBM 8514/A: H_SYNC_WID write 0EE8 = %d\n", val + 1); + dev->hsync_width = val; + ibm8514_log("IBM 8514/A compatible: (0x%04x): val=0x%02x, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); + svga_recalctimings(svga); break; case 0x12e8: case 0x12e9: - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { - WRITE8(port, dev->v_total_reg, val); - dev->v_total_reg &= 0x1fff; - dev->vtotal = dev->v_total_reg; - dev->vtotal++; - } + /*In preparation to switch from VGA to 8514/A mode*/ + WRITE8(port, dev->v_total_reg, val); + dev->v_total_reg &= 0x1fff; + dev->v_total = dev->v_total_reg + 1; + if (dev->interlace) + dev->v_total >>= 1; + + ibm8514_log("IBM 8514/A compatible: (0x%04x): vtotal=0x%02x.\n", port, val); + svga_recalctimings(svga); break; case 0x16e8: case 0x16e9: - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { + /*In preparation to switch from VGA to 8514/A mode*/ + if (!dev->on[0] || !dev->on[1]) { WRITE8(port, dev->v_disp, val); dev->v_disp &= 0x1fff; - dev->vdisp = dev->v_disp; - dev->vdisp >>= 1; - dev->vdisp++; + dev->vdisp = (dev->v_disp + 1) >> 1; } - ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->vdisp); + ibm8514_log("IBM 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); + ibm8514_log("IBM 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); + svga_recalctimings(svga); break; case 0x1ae8: case 0x1ae9: - if (((dev->disp_cntl & 0x60) == 0x20) || (((dev->disp_cntl & 0x60) == 0x40) && !(dev->accel.advfunc_cntl & 0x04))) { - WRITE8(port, dev->v_sync_start, val); - dev->v_sync_start &= 0x1fff; - dev->vsyncstart = dev->v_sync_start; - dev->vsyncstart++; - } + /*In preparation to switch from VGA to 8514/A mode*/ + WRITE8(port, dev->v_sync_start, val); + dev->v_sync_start &= 0x1fff; + dev->v_syncstart = dev->v_sync_start + 1; + if (dev->interlace) + dev->v_syncstart >>= 1; + + ibm8514_log("IBM 8514/A compatible: V_SYNCSTART write 1AE8 = %d\n", dev->v_syncstart); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncstart=0x%02x.\n", port, val); + svga_recalctimings(svga); break; case 0x1ee8: case 0x1ee9: - ibm8514_log("IBM 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); + ibm8514_log("IBM 8514/A compatible: V_SYNC_WID write 1EE8 = %02x\n", val); + ibm8514_log("IBM 8514/A compatible: (0x%04x): vsyncwidth=0x%02x.\n", port, val); + svga_recalctimings(svga); break; case 0x22e8: - dev->disp_cntl = val & 0x7e; - dev->interlace = !!(val & 0x10); - ibm8514_log("IBM 8514/A: DISP_CNTL write 22E8 = %02x, interlace = %d\n", dev->disp_cntl, dev->interlace); + dev->disp_cntl = val; + dev->interlace = !!(dev->disp_cntl & 0x10); + ibm8514_log("IBM 8514/A compatible: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); + svga_recalctimings(svga); break; case 0x42e8: - old = dev->subsys_stat; if (val & 1) dev->subsys_stat &= ~1; if (val & 2) @@ -1001,14 +1002,14 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) case 0x4ae8: case 0x4ae9: WRITE8(port, dev->accel.advfunc_cntl, val); - dev->on[port & 1] = dev->accel.advfunc_cntl & 0x01; - vga_on = !dev->on[port & 1]; - dev->vendor_mode[port & 1] = 0; - ibm8514_log("IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 4); + dev->on[0] = dev->accel.advfunc_cntl & 0x01; + vga_on = !dev->on[0]; + dev->vendor_mode[0] = 0; + ibm8514_log("[%04X:%08X]: IBM 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", CS, cpu_state.pc, port, dev->on[port & 1], dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + ibm8514_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); break; - default: break; } @@ -1031,73 +1032,14 @@ ibm8514_accel_outw(uint16_t port, uint16_t val, void *priv) ibm8514_accel_out(port, val, svga, 2); } -static uint32_t -ibm8514_accel_in(uint16_t port, svga_t *svga, int len) +uint16_t +ibm8514_accel_in_fifo(svga_t *svga, uint16_t port, int len) { - ibm8514_t *dev = (ibm8514_t *) svga->dev8514; - uint32_t temp = 0; - int cmd; - int vpos = 0; - int vblankend = svga->vblankstart + svga->crtc[0x16]; + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint16_t temp = 0; + int cmd = 0; switch (port) { - case 0x2e8: - vpos = dev->vc & 0x7ff; - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) - temp |= 2; - } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) - temp |= 2; - } - break; - - case 0x6e8: - temp = dev->hdisped; - break; - - case 0x22e8: - temp = dev->disp_cntl; - break; - - case 0x26e8: - if (len == 1) - temp = dev->htotal & 0xff; - else - temp = dev->htotal; - break; - case 0x26e9: - if (len == 1) - temp = dev->htotal >> 8; - break; - - case 0x2ee8: - temp = dev->subsys_cntl; - break; - - case 0x42e8: - cmd = dev->accel.cmd >> 13; - vpos = dev->vc & 0x7ff; - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if (vpos >= svga->vblankstart || vpos <= vblankend) - dev->subsys_stat |= 1; - } else { - if (vpos >= svga->vblankstart && vpos <= vblankend) - dev->subsys_stat |= 1; - } - if (len != 1) { - temp = dev->subsys_stat | 0xa0 | 0x8000; - } else - temp = dev->subsys_stat | 0xa0; - break; - - case 0x42e9: - if (len == 1) - temp |= 0x80; - break; - case 0x82e8: case 0xc2e8: if (len != 1) @@ -1115,6 +1057,11 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) temp = dev->test; break; + case 0x96e8: + if (len != 1) + temp = dev->accel.maj_axis_pcnt; + break; + case 0x9ae8: case 0xdae8: if (len != 1) { @@ -1143,26 +1090,82 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) case 0xe2e8: case 0xe6e8: if (ibm8514_cpu_dest(svga)) { - if (len == 1) { - ; // READ_PIXTRANS_BYTE_IO(0) - } else { + if (len != 1) { cmd = (dev->accel.cmd >> 13); - READ_PIXTRANS_WORD(dev->accel.cx, 0) + READ_PIXTRANS_WORD(dev->accel.cx, 0); if (dev->accel.input && !dev->accel.odd_in && !dev->accel.sx) { temp &= ~0xff00; temp |= (dev->vram[(dev->accel.newdest_in + dev->accel.cur_x) & dev->vram_mask] << 8); } + ibm8514_accel_out_pixtrans(svga, port, temp, len); } - ibm8514_accel_out_pixtrans(svga, port, temp, len); } break; - case 0xe2e9: - case 0xe6e9: - if (ibm8514_cpu_dest(svga)) { - if (len == 1) { - ; // READ_PIXTRANS_BYTE_IO(1) - ibm8514_accel_out_pixtrans(svga, port, temp, len); - } + + default: + break; + } + return temp; +} + +uint8_t +ibm8514_accel_in(uint16_t port, svga_t *svga) +{ + ibm8514_t *dev = (ibm8514_t *) svga->dev8514; + uint8_t temp = 0; + uint16_t clip_b_ibm = dev->accel.multifunc[3]; + uint16_t clip_r_ibm = dev->accel.multifunc[4]; + int cmd = (dev->accel.cmd >> 13); + + switch (port) { + case 0x2e8: + if (dev->vc == dev->v_syncstart) + temp |= 2; + + ibm8514_log("0x2E8 read: Display Status=%02x.\n", temp); + break; + + case 0x6e8: + temp = dev->hdisped; + break; + + case 0x22e8: + temp = dev->disp_cntl; + break; + + case 0x26e8: + case 0x26e9: + READ8(port, dev->htotal); + break; + + case 0x2ee8: + temp = dev->subsys_cntl; + break; + case 0x2ee9: + temp = 0xff; + break; + + case 0x42e8: + case 0x42e9: + if (dev->vc == dev->v_syncstart) + dev->subsys_stat |= 1; + + if (cmd == 6) { + if (((dev->accel.dx) >= dev->accel.clip_left) && ((dev->accel.dx) <= clip_r_ibm) && ((dev->accel.dy) >= dev->accel.clip_top) && ((dev->accel.dy) <= clip_b_ibm)) + temp |= 2; + } else { + if (((dev->accel.cx) >= dev->accel.clip_left) && ((dev->accel.dx) <= clip_r_ibm) && ((dev->accel.cy) >= dev->accel.clip_top) && ((dev->accel.cy) <= clip_b_ibm)) + temp |= 2; + } + + if (!dev->force_busy) + temp |= 8; + + if (port & 1) + temp = 0x80; + else { + temp |= (dev->subsys_stat | 0x80); + temp |= 0x20; } break; @@ -1176,16 +1179,29 @@ static uint8_t ibm8514_accel_inb(uint16_t port, void *priv) { svga_t *svga = (svga_t *) priv; + uint8_t temp; - return ibm8514_accel_in(port, svga, 1); + if (port & 0x8000) + temp = ibm8514_accel_in_fifo(svga, port, 1); + else + temp = ibm8514_accel_in(port, svga); + + return temp; } static uint16_t ibm8514_accel_inw(uint16_t port, void *priv) { svga_t *svga = (svga_t *) priv; + uint16_t temp; - return ibm8514_accel_in(port, svga, 2); + if (port & 0x8000) + temp = ibm8514_accel_in_fifo(svga, port, 2); + else { + temp = ibm8514_accel_in(port, svga); + temp |= (ibm8514_accel_in(port + 1, svga) << 8); + } + return temp; } void @@ -2285,7 +2301,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat WRITE(dev->accel.dest + dev->accel.cx, dest_dat); } } - mix_dat <<= 1; mix_dat |= 1; if (dev->bpp) @@ -2390,9 +2405,9 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sx += (dev->accel.cur_x & 3); } - if (dev->accel.cmd & 0x20) { + if (dev->accel.cmd & 0x20) dev->accel.cx -= (dev->accel.sx) + 1; - } else + else dev->accel.cx += (dev->accel.sx) + 1; if (dev->accel.cmd & 2) { @@ -2448,6 +2463,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } } + mix_dat <<= 1; mix_dat |= 1; @@ -2525,6 +2541,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } } + mix_dat <<= 1; mix_dat |= 1; if (dev->bpp) @@ -2987,9 +3004,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else dev->accel.oldcy = dev->accel.cy - 1; - dev->accel.oldcx = 0; - - ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cur_x_nolimit, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.clip_left, clip_r, dev->accel.clip_top, clip_b, compare_mode, dev->accel.multifunc[0x0a]); + ibm8514_log("Polygon Boundary activated=%04x, len=%d, cur(%d,%d), frgdmix=%02x, err=%d, clipping: l=%d, r=%d, t=%d, b=%d, pixcntl=%02x.\n", dev->accel.cmd, dev->accel.sy, dev->accel.cx, dev->accel.cy, dev->accel.frgd_mix & 0x1f, dev->accel.err_term, dev->accel.multifunc[2], dev->accel.multifunc[4], dev->accel.clip_top, clip_b, dev->accel.multifunc[0x0a]); if (ibm8514_cpu_src(svga)) { dev->data_available = 0; @@ -3103,10 +3118,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } else { while (count-- && (dev->accel.sy >= 0)) { - if (dev->accel.cx < 0) - dev->accel.cx = 0; - if (dev->accel.cy < 0) - dev->accel.cy = 0; + if (dev->accel.cx < dev->accel.clip_left) + dev->accel.cx = dev->accel.clip_left; if (dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { @@ -3136,12 +3149,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if ((dev->accel.cmd & 0x14) == 0x14) { if (dev->accel.sy) { - if (dev->accel.cmd & 0x40) { + if (dev->accel.oldcy != dev->accel.cy) { WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } else { - if (dev->accel.oldcy != dev->accel.cy) { - WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); - } } } } @@ -3159,6 +3168,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; if (dev->accel.cmd & 0x40) { + dev->accel.oldcy = dev->accel.cy; if (dev->accel.cmd & 0x80) dev->accel.cy++; else @@ -3385,6 +3395,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } + mix_dat >>= 1; if (dev->bpp) cpu_dat >>= 16; @@ -3452,7 +3463,6 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } else { while (count-- && (dev->accel.sy >= 0)) { if (dev->accel.dx >= dev->accel.clip_left && dev->accel.dx <= clip_r && dev->accel.dy >= dev->accel.clip_top && dev->accel.dy <= clip_b) { - if (pixcntl == 3) { if (!(dev->accel.cmd & 0x10) && ((frgd_mix != 3) || (bkgd_mix != 3))) { READ(dev->accel.src + dev->accel.cx, mix_dat); @@ -3496,6 +3506,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } + mix_dat <<= 1; mix_dat |= 1; if (dev->bpp) @@ -3655,6 +3666,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat WRITE(dev->accel.dest + dev->accel.dx, dest_dat); } } + dev->accel.temp_cnt--; mix_dat >>= 1; @@ -3779,6 +3791,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } } } + mix_dat <<= 1; mix_dat |= 1; @@ -4137,17 +4150,17 @@ ibm8514_poll(void *priv) if (dev->on[0] || dev->on[1]) { ibm8514_log("ON!\n"); if (!dev->linepos) { - if ((dev->displine == dev->hwcursor_latch.y) && dev->hwcursor_latch.ena) { + if ((dev->displine == ((dev->hwcursor_latch.y < 0) ? 0 : dev->hwcursor_latch.y)) && dev->hwcursor_latch.ena) { dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - dev->hwcursor_latch.yoff; dev->hwcursor_oddeven = 0; } - if ((dev->displine == (dev->hwcursor_latch.y + 1)) && dev->hwcursor_latch.ena && dev->interlace) { + if ((dev->displine == (((dev->hwcursor_latch.y < 0) ? 0 : dev->hwcursor_latch.y) + 1)) && dev->hwcursor_latch.ena && dev->interlace) { dev->hwcursor_on = dev->hwcursor_latch.cur_ysize - (dev->hwcursor_latch.yoff + 1); dev->hwcursor_oddeven = 1; } - timer_advance_u64(&svga->timer8514, dev->dispofftime); + timer_advance_u64(&svga->timer, dev->dispofftime); svga->cgastat |= 1; dev->linepos = 1; @@ -4173,7 +4186,7 @@ ibm8514_poll(void *priv) if (dev->hwcursor_on) { if (svga->hwcursor_draw) - svga->hwcursor_draw(svga, dev->displine + svga->y_add); + svga->hwcursor_draw(svga, (dev->displine + svga->y_add + ((dev->hwcursor_latch.y >= 0) ? 0 : dev->hwcursor_latch.y)) & 2047); dev->hwcursor_on--; if (dev->hwcursor_on && dev->interlace) dev->hwcursor_on--; @@ -4192,7 +4205,7 @@ ibm8514_poll(void *priv) if (dev->displine > 1500) dev->displine = 0; } else { - timer_advance_u64(&svga->timer8514, dev->dispontime); + timer_advance_u64(&svga->timer, dev->dispontime); if (dev->dispon) svga->cgastat &= ~1; dev->hdisp_on = 0; @@ -4215,7 +4228,7 @@ ibm8514_poll(void *priv) } dev->vc++; - dev->vc &= 0x7ff; + dev->vc &= 0xfff; if (dev->vc == dev->dispend) { dev->dispon = 0; @@ -4289,44 +4302,38 @@ ibm8514_recalctimings(svga_t *svga) } else #endif { - if (dev->on[0] || dev->on[1]) { - dev->h_disp = dev->hdisp; - dev->h_total = dev->htotal + 1; - dev->h_blankstart = dev->hblankstart; - dev->h_blank_end_val = dev->hblank_end_val; - dev->v_total = dev->vtotal; - dev->v_syncstart = dev->vsyncstart; - dev->dispend = dev->vdisp; - dev->rowcount = !!(dev->disp_cntl & 0x08); - - if (dev->dispend == 766) - dev->dispend += 2; - - if (dev->accel.advfunc_cntl & 4) { - dev->pitch = 1024; - if (!dev->h_disp) { - dev->h_disp = 1024; - dev->dispend = 768; - } - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { - dev->pitch = 640; - if (!dev->h_disp) { + if (dev->on[0]) { + dev->h_total = dev->htotal + 1; + dev->rowcount = !!(dev->disp_cntl & 0x08); + + if (dev->accel.advfunc_cntl & 0x01) { + if (dev->accel.advfunc_cntl & 0x04) { + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + } else { dev->h_disp = 640; dev->dispend = 480; } - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + } else { + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; } - if (dev->interlace) { + if (dev->accel.advfunc_cntl & 0x04) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + + if (dev->dispend == 766) + dev->dispend += 2; + + if (dev->dispend == 478) + dev->dispend += 2; + + if (dev->interlace) dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; - } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; - } + dev->pitch = 1024; dev->rowoffset = 0x80; svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; @@ -4378,12 +4385,21 @@ ibm8514_mca_reset(void *priv) dev->on[0] = 0; dev->on[1] = 0; vga_on = 1; - ibm8514_mca_write(0x102, 0, svga); +#ifdef ATI_8514_ULTRA + if (dev->extensions) + ati8514_mca_write(0x102, 0, svga); + else +#endif + ibm8514_mca_write(0x102, 0, svga); } static void * ibm8514_init(const device_t *info) { +#ifdef ATI_8514_ULTRA + uint32_t bios_addr = 0; +#endif + if (svga_get_pri() == NULL) return NULL; @@ -4395,7 +4411,7 @@ ibm8514_init(const device_t *info) dev->vram_size = 1024 << 10; dev->vram = calloc(dev->vram_size, 1); - dev->changedvram = calloc(dev->vram_size >> 12, 1); + dev->changedvram = calloc((dev->vram_size >> 12) + 1, 1); dev->vram_mask = dev->vram_size - 1; dev->map8 = dev->pallook; dev->local = 0; @@ -4405,31 +4421,37 @@ ibm8514_init(const device_t *info) #ifdef ATI_8514_ULTRA dev->extensions = device_get_config_int("extensions"); + bios_addr = device_get_config_hex20("bios_addr"); switch (dev->extensions) { case 1: if (rom_present(BIOS_MACH8_ROM_PATH)) { - mach = (mach_t *) calloc(1, sizeof(mach_t)); + mach_t * mach = (mach_t *) calloc(1, sizeof(mach_t)); svga->ext8514 = mach; - ati8514_init(svga, svga->ext8514, svga->dev8514); if (dev->type & DEVICE_MCA) { rom_init(&dev->bios_rom, - BIOS_MACH8_ROM_PATH, - 0xc6800, 0x1000, 0x0fff, - 0x0800, MEM_MAPPING_EXTERNAL); - mem_mapping_disable(&dev->bios_rom.mapping); + BIOS_MACH8_ROM_PATH, + 0xc6000, 0x2000, 0x1fff, + 0, MEM_MAPPING_EXTERNAL); dev->pos_regs[0] = 0x88; dev->pos_regs[1] = 0x80; mca_add(ati8514_mca_read, ati8514_mca_write, ibm8514_mca_feedb, ibm8514_mca_reset, svga); ati_eeprom_load(&mach->eeprom, "ati8514_mca.nvr", 0); + mem_mapping_disable(&dev->bios_rom.mapping); } else { rom_init(&dev->bios_rom, - BIOS_MACH8_ROM_PATH, - 0xd0000, 0x1000, 0x0fff, - 0x0800, MEM_MAPPING_EXTERNAL); + BIOS_MACH8_ROM_PATH, + bios_addr, 0x1000, 0xfff, + 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios_rom2, + BIOS_MACH8_ROM_PATH, + bios_addr + 0x1000, 0x800, 0x7ff, + 0x1000, MEM_MAPPING_EXTERNAL); ati_eeprom_load(&mach->eeprom, "ati8514.nvr", 0); + mach->accel.scratch0 = (((bios_addr >> 7) - 0x1000) >> 4); } + ati8514_init(svga, svga->ext8514, svga->dev8514); break; } fallthrough; @@ -4454,8 +4476,6 @@ ibm8514_init(const device_t *info) } #endif - timer_add(&svga->timer8514, ibm8514_poll, svga, 1); - return svga; } @@ -4518,6 +4538,30 @@ static const device_config_t ext8514_config[] = { } } }, + { + .name = "bios_addr", + .description = "BIOS address", + .type = CONFIG_HEX20, + .default_string = "", + .default_int = 0xc8000, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "C800h", .value = 0xc8000 }, + { .description = "CA00h", .value = 0xca000 }, + { .description = "CC00h", .value = 0xcc000 }, + { .description = "CE00h", .value = 0xce000 }, + { .description = "D000h", .value = 0xd0000 }, + { .description = "D200h", .value = 0xd2000 }, + { .description = "D400h", .value = 0xd4000 }, + { .description = "D600h", .value = 0xd6000 }, + { .description = "D800h", .value = 0xd8000 }, + { .description = "DA00h", .value = 0xda000 }, + { .description = "DC00h", .value = 0xdc000 }, + { .description = "DE00h", .value = 0xde000 }, + { .description = "" } + }, + }, { .type = CONFIG_END } @@ -4526,7 +4570,7 @@ static const device_config_t ext8514_config[] = { // clang-format off const device_t gen8514_isa_device = { - .name = "Generic 8514/A clone (ISA)", + .name = "IBM 8514/A clone (ISA)", .internal_name = "8514_isa", .flags = DEVICE_AT | DEVICE_ISA, .local = 0, @@ -4536,7 +4580,11 @@ const device_t gen8514_isa_device = { { .available = NULL }, .speed_changed = ibm8514_speed_changed, .force_redraw = ibm8514_force_redraw, +#ifdef ATI_8514_ULTRA + .config = ext8514_config +#else .config = NULL +#endif }; const device_t ibm8514_mca_device = { @@ -4550,7 +4598,11 @@ const device_t ibm8514_mca_device = { { .available = NULL }, .speed_changed = ibm8514_speed_changed, .force_redraw = ibm8514_force_redraw, +#ifdef ATI_8514_ULTRA + .config = ext8514_config +#else .config = NULL +#endif }; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index 368312fcbc..5a73991c0c 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -36,10 +36,11 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -#define VGAWONDERXL 1 -#if defined(DEV_BRANCH) && defined(USE_XL24) -# define VGAWONDERXL24 2 -#endif +#define VGAWONDERXL 1 +#define VGAWONDERXLPLUS 2 +#ifdef USE_XL24 +# define VGAWONDERXL24 3 +#endif /* USE_XL24 */ #define BIOS_ATIKOR_PATH "roms/video/ati28800/atikorvga.bin" #define BIOS_ATIKOR_4620P_PATH_L "roms/machines/spc4620p/31005h.u8" @@ -52,13 +53,14 @@ #define BIOS_VGAXL_EVEN_PATH "roms/video/ati28800/xleven.bin" #define BIOS_VGAXL_ODD_PATH "roms/video/ati28800/xlodd.bin" -#if defined(DEV_BRANCH) && defined(USE_XL24) +#ifdef USE_XL24 # define BIOS_XL24_EVEN_PATH "roms/video/ati28800/112-14318-102.bin" # define BIOS_XL24_ODD_PATH "roms/video/ati28800/112-14319-102.bin" -#endif +#endif /* USE_XL24 */ -#define BIOS_ROM_PATH "roms/video/ati28800/bios.bin" -#define BIOS_VGAXL_ROM_PATH "roms/video/ati28800/ATI_VGAWonder_XL.bin" +#define BIOS_ROM_PATH "roms/video/ati28800/bios.bin" +#define BIOS_VGAXL_ROM_PATH "roms/video/ati28800/ATI_VGAWonder_XL.bin" +#define BIOS_VGAXL_PLUS_ROM_PATH "roms/video/ati28800/VGAWonder1024D_XL_Plus_VGABIOS_U19.BIN" typedef struct ati28800_t { svga_t svga; @@ -183,7 +185,7 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv) case 0x3C7: case 0x3C8: case 0x3C9: - if (ati28800->type == 1) + if ((ati28800->type == VGAWONDERXL) || (ati28800->type == VGAWONDERXLPLUS)) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); else svga_out(addr, val, svga); @@ -339,7 +341,7 @@ ati28800_in(uint16_t addr, void *priv) case 0x3C7: case 0x3C8: case 0x3C9: - if (ati28800->type == 1) + if ((ati28800->type == VGAWONDERXL) || (ati28800->type == VGAWONDERXLPLUS)) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); return svga_in(addr, svga); @@ -609,7 +611,17 @@ ati28800_init(const device_t *info) ati28800->svga.ramdac = device_add(&sc11486_ramdac_device); break; -#if defined(DEV_BRANCH) && defined(USE_XL24) + case VGAWONDERXLPLUS: + ati28800->id = 6; + rom_init(&ati28800->bios_rom, + BIOS_VGAXL_PLUS_ROM_PATH, + 0xc0000, 0x8000, 0x7fff, + 0, MEM_MAPPING_EXTERNAL); + ati28800->svga.ramdac = device_add(&sc11483_ramdac_device); + ati28800->memory = 1024; + break; + +#ifdef USE_XL24 case VGAWONDERXL24: ati28800->id = 6; rom_init_interleaved(&ati28800->bios_rom, @@ -618,7 +630,7 @@ ati28800_init(const device_t *info) 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); break; -#endif +#endif /* USE_XL24 */ default: ati28800->id = 5; @@ -653,11 +665,15 @@ ati28800_init(const device_t *info) ati_eeprom_load(&ati28800->eeprom, "ati28800xl.nvr", 0); break; -#if defined(DEV_BRANCH) && defined(USE_XL24) + case VGAWONDERXLPLUS: + ati_eeprom_load(&ati28800->eeprom, "ati28800_wonder1024d_xl_plus.nvr", 0); + break; + +#ifdef USE_XL24 case VGAWONDERXL24: ati_eeprom_load(&ati28800->eeprom, "ati28800xl24.nvr", 0); break; -#endif +#endif /* USE_XL24 */ default: ati_eeprom_load(&ati28800->eeprom, "ati28800.nvr", 0); @@ -685,13 +701,19 @@ compaq_ati28800_available(void) return (rom_present(BIOS_VGAXL_ROM_PATH)); } -#if defined(DEV_BRANCH) && defined(USE_XL24) +static int +ati28800_wonder1024d_xl_plus_available(void) +{ + return (rom_present(BIOS_VGAXL_PLUS_ROM_PATH)); +} + +#ifdef USE_XL24 static int ati28800_wonderxl24_available(void) { return (rom_present(BIOS_XL24_EVEN_PATH) && rom_present(BIOS_XL24_ODD_PATH)); } -#endif +#endif /* USE_XL24 */ static void ati28800_close(void *priv) @@ -749,7 +771,7 @@ static const device_config_t ati28800_config[] = { } }; -#if defined(DEV_BRANCH) && defined(USE_XL24) +#ifdef USE_XL24 static const device_config_t ati28800_wonderxl_config[] = { { .name = "memory", @@ -778,7 +800,7 @@ static const device_config_t ati28800_wonderxl_config[] = { .type = CONFIG_END } }; -#endif +#endif /* USE_XL24 */ // clang-format on const device_t ati28800_device = { @@ -851,7 +873,21 @@ const device_t compaq_ati28800_device = { .config = ati28800_config }; -#if defined(DEV_BRANCH) && defined(USE_XL24) +const device_t ati28800_wonder1024d_xl_plus_device = { + .name = "ATI 28800-6 (ATI VGA Wonder 1024D XL Plus)", + .internal_name = "ati28800_wonder1024d_xl_plus", + .flags = DEVICE_ISA, + .local = VGAWONDERXLPLUS, + .init = ati28800_init, + .close = ati28800_close, + .reset = NULL, + { .available = ati28800_wonder1024d_xl_plus_available }, + .speed_changed = ati28800_speed_changed, + .force_redraw = ati28800_force_redraw, + .config = NULL +}; + +#ifdef USE_XL24 const device_t ati28800_wonderxl24_device = { .name = "ATI-28800 (VGA Wonder XL24)", .internal_name = "ati28800w", @@ -865,4 +901,4 @@ const device_t ati28800_wonderxl24_device = { .force_redraw = ati28800_force_redraw, .config = ati28800_wonderxl_config }; -#endif +#endif /* USE_XL24 */ diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 04d497f289..1c79ae1d5f 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -248,12 +248,12 @@ typedef struct mach64_t { fifo_entry_t fifo[FIFO_SIZE]; atomic_int fifo_read_idx; atomic_int fifo_write_idx; + atomic_int blitter_busy; thread_t *fifo_thread; event_t *wake_fifo_thread; event_t *fifo_not_full_event; - int blitter_busy; uint64_t blitter_time; uint64_t status_time; @@ -333,7 +333,8 @@ enum { enum { SRC_PATT_EN = 1, SRC_PATT_ROT_EN = 2, - SRC_LINEAR_EN = 4 + SRC_LINEAR_EN = 4, + SRC_BYTE_ALIGN = 8 }; enum { @@ -538,7 +539,7 @@ mach64_recalctimings(svga_t *svga) break; case BPP_8: if (mach64->type != MACH64_GX) - svga->render = svga_render_8bpp_highres; + svga->render = svga_render_8bpp_clone_highres; svga->hdisp <<= 3; svga->rowoffset >>= 1; break; @@ -649,9 +650,8 @@ mach64_updatemapping(mach64_t *mach64) static void mach64_update_irqs(mach64_t *mach64) { - if (!mach64->pci) { + if (!mach64->pci) return; - } if ((mach64->crtc_int_cntl & 0xaa0024) & ((mach64->crtc_int_cntl << 1) & 0xaa0024)) pci_set_irq(mach64->pci_slot, PCI_INTA, &mach64->irq_state); @@ -659,7 +659,6 @@ mach64_update_irqs(mach64_t *mach64) pci_clear_irq(mach64->pci_slot, PCI_INTA, &mach64->irq_state); } -#if 0 static __inline void wake_fifo_thread(mach64_t *mach64) { @@ -674,7 +673,6 @@ mach64_wait_fifo_idle(mach64_t *mach64) thread_wait_event(mach64->fifo_not_full_event, 1); } } -#endif #define READ8(addr, var) \ switch ((addr) &3) { \ @@ -1174,7 +1172,6 @@ mach64_accel_write_fifo_l(mach64_t *mach64, uint32_t addr, uint32_t val) } } -#if 0 static void fifo_thread(void *param) { @@ -1222,11 +1219,53 @@ static void mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t type) { fifo_entry_t *fifo = &mach64->fifo[mach64->fifo_write_idx & FIFO_MASK]; + int limit = 0; + + switch (type) { + case FIFO_WRITE_BYTE: + switch (addr & 0x3ff) { + case 0x11b: + limit = 1; + break; + default: + break; + } + break; + case FIFO_WRITE_WORD: + switch (addr & 0x3fe) { + case 0x11a: + limit = 1; + break; + default: + break; + } + break; + case FIFO_WRITE_DWORD: + switch (addr & 0x3fc) { + case 0x118: + limit = 1; + break; + default: + break; + } + break; + default: + break; + } - if (FIFO_FULL) { - thread_reset_event(mach64->fifo_not_full_event); + if (limit) { + if (FIFO_ENTRIES >= 16) { + thread_reset_event(mach64->fifo_not_full_event); + if (FIFO_ENTRIES >= 16) { + thread_wait_event(mach64->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } + } else { if (FIFO_FULL) { - thread_wait_event(mach64->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + thread_reset_event(mach64->fifo_not_full_event); + if (FIFO_FULL) { + thread_wait_event(mach64->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } } } @@ -1238,11 +1277,18 @@ mach64_queue(mach64_t *mach64, uint32_t addr, uint32_t val, uint32_t type) if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) wake_fifo_thread(mach64); } -#endif void mach64_start_fill(mach64_t *mach64) { + mach64->accel.dst_pix_width = mach64->dp_pix_width & 7; + mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7; + mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7; + + mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width]; + mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width]; + mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width]; + mach64->accel.dst_x = 0; mach64->accel.dst_y = 0; @@ -1256,7 +1302,8 @@ mach64_start_fill(mach64_t *mach64) mach64->accel.dst_width = (mach64->dst_height_width >> 16) & 0x1fff; mach64->accel.dst_height = mach64->dst_height_width & 0x1fff; - if (((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC) { + if ((((mach64->dp_src >> 16) & 7) == MONO_SRC_BLITSRC) && + ((mach64->src_cntl & (SRC_LINEAR_EN | SRC_BYTE_ALIGN)) == (SRC_LINEAR_EN | SRC_BYTE_ALIGN))) { if (mach64->accel.dst_width & 7) mach64->accel.dst_width = (mach64->accel.dst_width & ~7) + 8; } @@ -1308,14 +1355,6 @@ mach64_start_fill(mach64_t *mach64) mach64->accel.source_fg = (mach64->dp_src >> 8) & 7; mach64->accel.source_mix = (mach64->dp_src >> 16) & 7; - mach64->accel.dst_pix_width = mach64->dp_pix_width & 7; - mach64->accel.src_pix_width = (mach64->dp_pix_width >> 8) & 7; - mach64->accel.host_pix_width = (mach64->dp_pix_width >> 16) & 7; - - mach64->accel.dst_size = mach64_width[mach64->accel.dst_pix_width]; - mach64->accel.src_size = mach64_width[mach64->accel.src_pix_width]; - mach64->accel.host_size = mach64_width[mach64->accel.host_pix_width]; - if (mach64->accel.src_size == WIDTH_1BIT) mach64->accel.src_offset <<= 3; else @@ -1824,6 +1863,7 @@ mach64_blit(uint32_t cpu_dat, int count, mach64_t *mach64) cpu_dat >>= (count & 7); else cpu_dat <<= (count & 7); + count &= ~7; } } @@ -2538,26 +2578,26 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x101: case 0x102: case 0x103: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_off_pitch); break; case 0x104: case 0x105: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_y_x); break; case 0x108: case 0x109: case 0x11c: case 0x11d: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->dst_y_x); break; case 0x10c: case 0x10d: case 0x10e: case 0x10f: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_y_x); break; case 0x110: @@ -2572,7 +2612,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x11b: case 0x11e: case 0x11f: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_height_width); break; @@ -2580,28 +2620,28 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x121: case 0x122: case 0x123: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_lnth); break; case 0x124: case 0x125: case 0x126: case 0x127: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_err); break; case 0x128: case 0x129: case 0x12a: case 0x12b: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_inc); break; case 0x12c: case 0x12d: case 0x12e: case 0x12f: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_bres_dec); break; @@ -2609,7 +2649,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x131: case 0x132: case 0x133: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_cntl); break; @@ -2617,75 +2657,75 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x181: case 0x182: case 0x183: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_off_pitch); break; case 0x184: case 0x185: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x); break; case 0x188: case 0x189: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_y_x); break; case 0x18c: case 0x18d: case 0x18e: case 0x18f: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x); break; case 0x190: case 0x191: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_height1_width1); break; case 0x194: case 0x195: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height1_width1); break; case 0x198: case 0x199: case 0x19a: case 0x19b: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height1_width1); break; case 0x19c: case 0x19d: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x_start); break; case 0x1a0: case 0x1a1: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_y_x_start); break; case 0x1a4: case 0x1a5: case 0x1a6: case 0x1a7: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_y_x_start); break; case 0x1a8: case 0x1a9: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr + 2, mach64->src_height2_width2); break; case 0x1ac: case 0x1ad: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height2_width2); break; case 0x1b0: case 0x1b1: case 0x1b2: case 0x1b3: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_height2_width2); break; @@ -2693,7 +2733,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x1b5: case 0x1b6: case 0x1b7: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->src_cntl); break; @@ -2701,7 +2741,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x241: case 0x242: case 0x243: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->host_cntl); break; @@ -2709,14 +2749,14 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x281: case 0x282: case 0x283: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_reg0); break; case 0x284: case 0x285: case 0x286: case 0x287: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_reg1); break; @@ -2724,7 +2764,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x289: case 0x28a: case 0x28b: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->pat_cntl); break; @@ -2732,7 +2772,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x2a1: case 0x2a8: case 0x2a9: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); break; case 0x2a4: @@ -2741,7 +2781,7 @@ mach64_ext_readb(uint32_t addr, void *priv) fallthrough; case 0x2aa: case 0x2ab: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); break; @@ -2749,7 +2789,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x2ad: case 0x2b4: case 0x2b5: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); break; case 0x2b0: @@ -2758,7 +2798,7 @@ mach64_ext_readb(uint32_t addr, void *priv) fallthrough; case 0x2b6: case 0x2b7: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); break; @@ -2766,14 +2806,14 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x2c1: case 0x2c2: case 0x2c3: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_bkgd_clr); break; case 0x2c4: case 0x2c5: case 0x2c6: case 0x2c7: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_frgd_clr); break; @@ -2781,7 +2821,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x2c9: case 0x2ca: case 0x2cb: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->write_mask); break; @@ -2789,7 +2829,7 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x2cd: case 0x2ce: case 0x2cf: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->chain_mask); break; @@ -2797,21 +2837,21 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x2d1: case 0x2d2: case 0x2d3: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_pix_width); break; case 0x2d4: case 0x2d5: case 0x2d6: case 0x2d7: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_mix); break; case 0x2d8: case 0x2d9: case 0x2da: case 0x2db: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dp_src); break; @@ -2819,53 +2859,61 @@ mach64_ext_readb(uint32_t addr, void *priv) case 0x301: case 0x302: case 0x303: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_clr); break; case 0x304: case 0x305: case 0x306: case 0x307: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_mask); break; case 0x308: case 0x309: case 0x30a: case 0x30b: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->clr_cmp_cntl); break; case 0x310: case 0x311: + if (!mach64->blitter_busy) + wake_fifo_thread(mach64); + ret = 0; + if (FIFO_FULL) + ret = 0xff; break; case 0x320: case 0x321: case 0x322: case 0x323: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->context_mask); break; case 0x330: case 0x331: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr, mach64->dst_cntl); break; case 0x332: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr - 2, mach64->src_cntl); break; case 0x333: - //mach64_wait_fifo_idle(mach64); + mach64_wait_fifo_idle(mach64); READ8(addr - 3, mach64->pat_cntl); break; case 0x338: - ret = 0; + if (!mach64->blitter_busy) + wake_fifo_thread(mach64); + + ret = FIFO_EMPTY ? 0 : 1; break; default: @@ -2884,7 +2932,7 @@ mach64_ext_readw(uint32_t addr, void *priv) uint16_t ret; if (!(addr & 0x400)) { - mach64_log("nmach64_ext_readw: addr=%04x\n", addr); + mach64_log("mach64_ext_readw: addr=%04x\n", addr); ret = 0xffff; } else switch (addr & 0x3ff) { @@ -3048,9 +3096,9 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv) break; } - mach64_log("nmach64_ext_writeb: addr=%04x val=%02x\n", addr, val); + mach64_log("mach64_ext_writeb: addr=%04x val=%02x\n", addr, val); } else if (addr & 0x300) { - mach64_accel_write_fifo(mach64, addr & 0x3ff, val); + mach64_queue(mach64, addr & 0x3ff, val, FIFO_WRITE_BYTE); } else { switch (addr & 0x3ff) { case 0x00: @@ -3293,14 +3341,11 @@ mach64_ext_writew(uint32_t addr, uint16_t val, void *priv) mach64_ext_writeb(addr, val, priv); mach64_ext_writeb(addr + 1, val >> 8, priv); } else if (addr & 0x300) { - mach64_accel_write_fifo_w(mach64, addr & 0x3fe, val); - } else - switch (addr & 0x3fe) { - default: - mach64_ext_writeb(addr, val, priv); - mach64_ext_writeb(addr + 1, val >> 8, priv); - break; - } + mach64_queue(mach64, addr & 0x3fe, val, FIFO_WRITE_WORD); + } else { + mach64_ext_writeb(addr, val, priv); + mach64_ext_writeb(addr + 1, val >> 8, priv); + } } void mach64_ext_writel(uint32_t addr, uint32_t val, void *priv) @@ -3314,14 +3359,11 @@ mach64_ext_writel(uint32_t addr, uint32_t val, void *priv) mach64_ext_writew(addr, val, priv); mach64_ext_writew(addr + 2, val >> 16, priv); } else if (addr & 0x300) { - mach64_accel_write_fifo_l(mach64, addr & 0x3fc, val); - } else - switch (addr & 0x3fc) { - default: - mach64_ext_writew(addr, val, priv); - mach64_ext_writew(addr + 2, val >> 16, priv); - break; - } + mach64_queue(mach64, addr & 0x3fc, val, FIFO_WRITE_DWORD); + } else { + mach64_ext_writew(addr, val, priv); + mach64_ext_writew(addr + 2, val >> 16, priv); + } } uint8_t @@ -3527,12 +3569,10 @@ uint16_t mach64_ext_inw(uint16_t port, void *priv) { uint16_t ret; - switch (port) { - default: - ret = mach64_ext_inb(port, priv); - ret |= (mach64_ext_inb(port + 1, priv) << 8); - break; - } + + ret = mach64_ext_inb(port, priv); + ret |= (mach64_ext_inb(port + 1, priv) << 8); + mach64_log("mach64_ext_inw : port %04X ret %04X\n", port, ret); return ret; } @@ -3540,6 +3580,7 @@ uint32_t mach64_ext_inl(uint16_t port, void *priv) { uint32_t ret; + switch (port) { case 0x56ec: ret = mach64_ext_readl(0x400 | 0xb4, priv); @@ -3737,23 +3778,15 @@ void mach64_ext_outw(uint16_t port, uint16_t val, void *priv) { mach64_log("mach64_ext_outw : port %04X val %04X\n", port, val); - switch (port) { - default: - mach64_ext_outb(port, val, priv); - mach64_ext_outb(port + 1, val >> 8, priv); - break; - } + mach64_ext_outb(port, val, priv); + mach64_ext_outb(port + 1, val >> 8, priv); } void mach64_ext_outl(uint16_t port, uint32_t val, void *priv) { mach64_log("mach64_ext_outl : port %04X val %08X\n", port, val); - switch (port) { - default: - mach64_ext_outw(port, val, priv); - mach64_ext_outw(port + 2, val >> 16, priv); - break; - } + mach64_ext_outw(port, val, priv); + mach64_ext_outw(port + 2, val >> 16, priv); } static uint8_t @@ -4546,6 +4579,11 @@ mach64_common_init(const device_t *info) mach64->dst_cntl = 3; + mach64->thread_run = 1; + mach64->wake_fifo_thread = thread_create_event(); + mach64->fifo_not_full_event = thread_create_event(); + mach64->fifo_thread = thread_create(fifo_thread, mach64); + mach64->i2c = i2c_gpio_init("ddc_ati_mach64"); mach64->ddc = ddc_init(i2c_gpio_get_bus(mach64->i2c)); @@ -4640,6 +4678,12 @@ mach64_close(void *priv) { mach64_t *mach64 = (mach64_t *) priv; + mach64->thread_run = 0; + thread_set_event(mach64->wake_fifo_thread); + thread_wait(mach64->fifo_thread); + thread_destroy_event(mach64->fifo_not_full_event); + thread_destroy_event(mach64->wake_fifo_thread); + svga_close(&mach64->svga); ddc_close(mach64->ddc); diff --git a/src/video/vid_ati_mach8.c b/src/video/vid_ati_mach8.c index be2c5d5472..d41f65ed98 100644 --- a/src/video/vid_ati_mach8.c +++ b/src/video/vid_ati_mach8.c @@ -37,6 +37,7 @@ #include <86box/i2c.h> #include <86box/vid_ddc.h> #include <86box/vid_8514a.h> +#include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/vid_ati_eeprom.h> @@ -315,8 +316,6 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 bkgd_sel = (mach->accel.dp_config >> 7) & 3; mono_src = (mach->accel.dp_config >> 5) & 3; - mach->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); - if ((mono_src == 2) || (bkgd_sel == 2) || (frgd_sel == 2) || mach_pixel_read(mach)) { mach->force_busy = 1; dev->force_busy = 1; @@ -817,7 +816,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (dev->accel.cur_y >= 0x600) dev->accel.dy |= ~0x5ff; - if ((mach->accel.dp_config == 0x5211) || (mach->accel.dp_config == 0x3251)) { + if (mach->accel.dp_config == 0x5211) { if (mach->accel.dest_x_end == 1024) { goto skip_dx; } @@ -1008,6 +1007,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 if (cpu_input) { if (mach->accel.dp_config == 0x3251) { + mach_log("DPCONFIG 3251: monosrc=%d, frgdsel=%d, bkgdsel=%d, pitch=%d.\n", mono_src, frgd_sel, bkgd_sel, dev->pitch); if (dev->accel.sy == mach->accel.height) return; } @@ -1386,15 +1386,7 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); } } - if (mach->accel.linedraw_opt & 0x04) { - if (count) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } - } else { + if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { if (dev->bpp) { WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); } else { @@ -1647,20 +1639,10 @@ mach_accel_start(int cmd_type, int cpu_input, int count, uint32_t mix_dat, uint3 } if ((mach->accel.dp_config & 0x10) && (cmd_type == 3)) { - if (mach->accel.linedraw_opt & 0x04) { - if (count) { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } - } + if (dev->bpp) { + WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); } else { - if (dev->bpp) { - WRITE((mach->accel.ge_offset << 1) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } else { - WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); - } + WRITE((mach->accel.ge_offset << 2) + ((dev->accel.cy) * (dev->pitch)) + (dev->accel.cx), dest_dat); } } } else @@ -2374,6 +2356,9 @@ mach_in(uint16_t addr, void *priv) if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; + if ((addr >= 0x3c6) && (addr <= 0x3c9) && (dev->on[0] || dev->on[1])) + addr -= 0xdc; + switch (addr) { case 0x1ce: temp = mach->index; @@ -2399,9 +2384,9 @@ mach_in(uint16_t addr, void *priv) } break; case 0xb7: - temp = mach->regs[0xb7] & ~8; + temp = mach->regs[0xb7] & ~0x08; if (ati_eeprom_read(&mach->eeprom)) - temp |= 8; + temp |= 0x08; break; case 0xbd: @@ -2429,21 +2414,6 @@ mach_in(uint16_t addr, void *priv) temp = svga_in(addr, svga); break; - case 0x3C6: - case 0x3C7: - case 0x3C8: - case 0x3C9: - rs2 = !!(mach->regs[0xa0] & 0x20); - rs3 = !!(mach->regs[0xa0] & 0x40); - if ((dev->local & 0xff) >= 0x02) { - if (mach->pci_bus && !mach->ramdac_type) - temp = ati68860_ramdac_in((addr & 3) | (rs2 << 2) | (rs3 << 3), svga->ramdac, svga); - else - temp = ati68875_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); - } else - temp = svga_in(addr, svga); - break; - case 0x3D4: temp = svga->crtcreg; break; @@ -2466,7 +2436,7 @@ mach_in(uint16_t addr, void *priv) static void ati8514_out(uint16_t addr, uint8_t val, void *priv) { - mach_log("ADDON OUT addr=%03x, val=%02x.\n", addr, val); + mach_log("[%04X:%08X]: ADDON OUT addr=%03x, val=%02x.\n", CS, cpu_state.pc, addr, val); svga_out(addr, val, priv); } @@ -2477,26 +2447,45 @@ ati8514_in(uint16_t addr, void *priv) temp = svga_in(addr, priv); - mach_log("ADDON IN addr=%03x, temp=%02x.\n", addr, temp); + mach_log("[%04X:%08X]: ADDON IN addr=%03x, temp=%02x.\n", CS, cpu_state.pc, addr, temp); return temp; } void ati8514_recalctimings(svga_t *svga) { - const mach_t *mach = (mach_t *) svga->ext8514; + mach_t *mach = (mach_t *) svga->ext8514; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; mach_log("ON0=%d, ON1=%d, vgahdisp=%d.\n", dev->on[0], dev->on[1], svga->hdisp); if (dev->on[0] || dev->on[1]) { - dev->h_disp = dev->hdisp; + mach_log("8514/A ON.\n"); dev->h_total = dev->htotal + 1; - dev->h_blankstart = dev->hblankstart; - dev->h_blank_end_val = dev->hblank_end_val; - dev->v_total = dev->vtotal; - dev->v_syncstart = dev->vsyncstart; dev->rowcount = !!(dev->disp_cntl & 0x08); - dev->dispend = dev->vdisp; + dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + mach->accel.ge_offset = dev->accel.ge_offset; + + mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0xfe); + if (dev->accel.advfunc_cntl & 0x01) { + if (dev->accel.advfunc_cntl & 0x04) { + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + } else { + dev->h_disp = 640; + dev->dispend = 480; + } + } else { + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + } + + if (dev->accel.advfunc_cntl & 0x04) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; + else + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; + + if (dev->interlace) + dev->dispend >>= 1; if (dev->dispend == 766) dev->dispend += 2; @@ -2504,28 +2493,12 @@ ati8514_recalctimings(svga_t *svga) if (dev->dispend == 598) dev->dispend += 2; - if (dev->accel.advfunc_cntl & 4) { - if (dev->h_disp != 800) { - dev->h_disp = 1024; - dev->dispend = 768; - } - svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { - svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } - - if (dev->interlace) { - dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; - } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; - } + if (dev->dispend == 478) + dev->dispend += 2; dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, advfunc_cntl=%x, shadow=%x.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, dev->accel.advfunc_cntl & 4, mach->shadow_set & 3); + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; } else { @@ -2598,57 +2571,49 @@ mach_recalctimings(svga_t *svga) if (dev->on[0] || dev->on[1]) { mach_log("8514/A ON.\n"); dev->h_total = dev->htotal + 1; - dev->v_total = dev->v_total_reg + 1; - dev->v_syncstart = dev->v_sync_start + 1; dev->rowcount = !!(dev->disp_cntl & 0x08); - - mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04); - if ((dev->hdisp != 1024) || dev->bpp) { - /*For VESA/ATI modes in 8514/A mode.*/ - dev->h_disp = dev->hdisp; - dev->dispend = dev->vdisp; - } else { - /*Default modes for 8514/A mode*/ - if (dev->accel.advfunc_cntl & 0x04) { - dev->h_disp = 1024; - dev->dispend = 768; + dev->accel.ge_offset = (mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16)); + mach->accel.ge_offset = dev->accel.ge_offset; + + mach_log("HDISP=%d, VDISP=%d, shadowset=%x, 8514/A mode=%x, clocksel=%02x.\n", dev->hdisp, dev->vdisp, mach->shadow_set & 0x03, dev->accel.advfunc_cntl & 0x04, mach->accel.clock_sel & 0xfe); + if (!dev->bpp) { + if (dev->accel.advfunc_cntl & 0x01) { + if (dev->accel.advfunc_cntl & 0x04) { + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; + } else { + dev->h_disp = 640; + dev->dispend = 480; + } } else { - dev->h_disp = 640; - dev->dispend = 480; + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; } + } else { + dev->h_disp = dev->hdisp; + dev->dispend = dev->vdisp; } - if (dev->dispend == 766) + svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); + if (mach->accel.clock_sel & 0x40) + svga->clock8514 *= 2; + + if (dev->interlace) + dev->dispend >>= 1; + + if (dev->dispend == 478) dev->dispend += 2; if (dev->dispend == 598) dev->dispend += 2; - if (dev->dispend == 478) + if (dev->dispend == 766) dev->dispend += 2; - if ((dev->local & 0xff) >= 0x02) { - if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { - if ((mach->shadow_set ^ mach->compat_mode) & 0x03) - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); - else - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { - if ((mach->shadow_set ^ mach->compat_mode) & 0x03) - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); - else - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } - - if (dev->interlace) { - dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; - } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; - } + if (dev->dispend == 1022) + dev->dispend += 2; + if ((dev->local & 0xff) >= 0x02) { mach_log("HDISP=%d.\n", dev->h_disp); dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; @@ -2696,58 +2661,38 @@ mach_recalctimings(svga_t *svga) break; } } - switch (mach->regs[0xb8] & 0xc0) { - case 0x40: - svga->clock8514 *= 2; - break; - case 0x80: - svga->clock8514 *= 3; - break; - case 0xc0: - svga->clock8514 *= 4; - break; - - default: - break; - } } else { - if ((dev->accel.advfunc_cntl ^ dev->modechange) & 0x04) { - if ((mach->shadow_set ^ mach->compat_mode) & 0x03) - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); - else - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 44900000.0; - } else { - if ((mach->shadow_set ^ mach->compat_mode) & 0x03) - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / svga->getclock((mach->accel.clock_sel >> 2) & 0x0f, svga->clock_gen); - else - svga->clock8514 = (cpuclock * (double) (1ULL << 32)) / 25175000.0; - } - - if (dev->interlace) { - dev->dispend >>= 1; - dev->v_syncstart >>= 2; - dev->v_total >>= 2; - } else { - dev->v_syncstart >>= 1; - dev->v_total >>= 1; - } - dev->pitch = dev->ext_pitch; dev->rowoffset = dev->ext_crt_pitch; - mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 4, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); + mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n", dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset, mach->accel.ext_ge_config & 0xcec0, mach->shadow_set & 3, dev->interlace); svga->map8 = dev->pallook; svga->render8514 = ibm8514_render_8bpp; - if (mach->regs[0xb8] & 0x40) - svga->clock8514 *= 2; } } if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { if (((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { - mach_log("VGA clock=%02x.\n", mach->regs[0xa7] & 0x80); svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen); - if (mach->regs[0xa7] & 0x80) - svga->clock *= 3; + mach_log("VGA clock=%02x.\n", mach->regs[0xa7] & 0x80); + if ((dev->local & 0xff) >= 0x02) { + if (mach->regs[0xb8] & 0x40) + svga->clock *= 2; + } else { + switch (mach->regs[0xb8] & 0xc0) { + case 0x40: + svga->clock *= 2; + break; + case 0x80: + svga->clock *= 3; + break; + case 0xc0: + svga->clock *= 4; + break; + + default: + break; + } + } switch (svga->gdcreg[5] & 0x60) { case 0x00: if (svga->seqregs[1] & 8) /*Low res (320)*/ @@ -2799,114 +2744,56 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u switch (port) { case 0x82e8: - case 0xc2e8: - case 0xf6ee: - if (len == 1) - dev->accel.cur_y = (dev->accel.cur_y & 0x700) | val; - else - dev->accel.cur_y = val & 0x7ff; - break; case 0x82e9: - case 0xc2e9: - case 0xf6ef: - if (len == 1) - dev->accel.cur_y = (dev->accel.cur_y & 0xff) | ((val & 0x07) << 8); - break; - case 0x86e8: - case 0xc6e8: - if (len == 1) - dev->accel.cur_x = (dev->accel.cur_x & 0x700) | val; - else - dev->accel.cur_x = val & 0x7ff; - break; case 0x86e9: + case 0xc2e8: + case 0xc2e9: + case 0xc6e8: case 0xc6e9: - if (len == 1) { - dev->accel.cur_x = (dev->accel.cur_x & 0xff) | ((val & 0x07) << 8); - } + ibm8514_accel_out_fifo(svga, port, val, len); + break; + case 0xf6ee: + ibm8514_accel_out_fifo(svga, 0x82e8, val, len); + break; + case 0xf6ef: + ibm8514_accel_out_fifo(svga, 0x82e9, val, len); break; case 0x8ae8: case 0xcae8: - if (len == 1) - dev->accel.desty_axstp = (dev->accel.desty_axstp & 0x3f00) | val; - else { - mach->accel.src_y = val; - dev->accel.desty = val & 0x07ff; - dev->accel.desty_axstp = val & 0x3fff; - if (val & 0x2000) - dev->accel.desty_axstp |= ~0x1fff; - } + ibm8514_accel_out_fifo(svga, port, val, len); + if (len != 1) + mach->accel.src_y = val; break; case 0x8ae9: + case 0x8ee9: case 0xcae9: - if (len == 1) { - dev->accel.desty_axstp = (dev->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - dev->accel.desty_axstp |= ~0x1fff; - } + case 0xcee9: + ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x8ee8: case 0xcee8: - if (len == 1) - dev->accel.destx_distp = (dev->accel.destx_distp & 0x3f00) | val; - else { - mach->accel.src_x = val; - dev->accel.destx = val & 0x07ff; - dev->accel.destx_distp = val & 0x3fff; - if (val & 0x2000) - dev->accel.destx_distp |= ~0x1fff; - } - break; - case 0x8ee9: - case 0xcee9: - if (len == 1) { - dev->accel.destx_distp = (dev->accel.destx_distp & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - dev->accel.destx_distp |= ~0x1fff; - } + ibm8514_accel_out_fifo(svga, port, val, len); + if (len != 1) + mach->accel.src_x = val; break; case 0x92e8: - if (len != 1) - dev->test = val; - fallthrough; - - case 0xd2e8: - if (len == 1) - dev->accel.err_term = (dev->accel.err_term & 0x3f00) | val; - else { - dev->accel.err_term = val & 0x3fff; - if (val & 0x2000) - dev->accel.err_term |= ~0x1fff; - } - break; case 0x92e9: + case 0x96e9: + case 0xd2e8: case 0xd2e9: - if (len == 1) { - dev->accel.err_term = (dev->accel.err_term & 0xff) | ((val & 0x3f) << 8); - if (val & 0x20) - dev->accel.err_term |= ~0x1fff; - } + case 0xd6e9: + ibm8514_accel_out_fifo(svga, port, val, len); break; case 0x96e8: case 0xd6e8: - if (len == 1) - dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0x0700) | val; - else { - mach->accel.test = val & 0x1fff; - dev->accel.maj_axis_pcnt = val & 0x07ff; - dev->accel.maj_axis_pcnt_no_limit = val; - } - break; - case 0x96e9: - case 0xd6e9: - if (len == 1) { - dev->accel.maj_axis_pcnt = (dev->accel.maj_axis_pcnt & 0xff) | ((val & 0x07) << 8); - } + ibm8514_accel_out_fifo(svga, port, val, len); + if (len != 1) + mach->accel.test = val & 0x1fff; break; case 0x9ae8: @@ -2952,12 +2839,11 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u dev->accel.cx = dev->accel.cur_x; dev->accel.cy = dev->accel.cur_y; - if (dev->accel.cur_x >= 0x600) { + if (dev->accel.cur_x >= 0x600) dev->accel.cx |= ~0x5ff; - } - if (dev->accel.cur_y >= 0x600) { + + if (dev->accel.cur_y >= 0x600) dev->accel.cy |= ~0x5ff; - } if (dev->accel.cmd & 0x1000) { ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); @@ -3163,56 +3049,22 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0xaae8: - case 0xeae8: - if (len == 1) - dev->accel.wrt_mask = (dev->accel.wrt_mask & 0x00ff) | val; - else { - dev->accel.wrt_mask = val; - mach_log("WrtMask=%04x.\n", val); - } - break; case 0xaae9: - case 0xeae9: - if (len == 1) - dev->accel.wrt_mask = (dev->accel.wrt_mask & 0xff00) | (val << 8); - break; - case 0xaee8: - case 0xeee8: - if (len == 1) - dev->accel.rd_mask = (dev->accel.rd_mask & 0x00ff) | val; - else { - dev->accel.rd_mask = val; - mach_log("ReadMask=%04x.\n", val); - } - break; case 0xaee9: - case 0xeee9: - if (len == 1) - dev->accel.rd_mask = (dev->accel.rd_mask & 0xff00) | (val << 8); - break; - case 0xb2e8: - case 0xf2e8: - if (len == 1) - dev->accel.color_cmp = (dev->accel.color_cmp & 0x00ff) | val; - else - dev->accel.color_cmp = val; - break; case 0xb2e9: - case 0xf2e9: - if (len == 1) - dev->accel.color_cmp = (dev->accel.color_cmp & 0xff00) | (val << 8); - break; - case 0xb6e8: - case 0xf6e8: - dev->accel.bkgd_mix = val & 0xff; - break; - case 0xbae8: + case 0xeae8: + case 0xeae9: + case 0xeee8: + case 0xeee9: + case 0xf2e8: + case 0xf2e9: + case 0xf6e8: case 0xfae8: - dev->accel.frgd_mix = val & 0xff; + ibm8514_accel_out_fifo(svga, port, val, len); break; case 0xbee8: @@ -3274,9 +3126,9 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u break; case 0x8eee: - if (len == 1) { + if (len == 1) mach->accel.patt_data[mach->accel.patt_data_idx] = val; - } else { + else { mach->accel.patt_data[mach->accel.patt_data_idx] = val & 0xff; mach->accel.patt_data[mach->accel.patt_data_idx + 1] = (val >> 8) & 0xff; if (mach->accel.mono_pattern_enable) @@ -3359,9 +3211,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } break; case 0xa2ef: - if (len == 1) { + if (len == 1) mach->accel.linedraw_opt = (mach->accel.linedraw_opt & 0x00ff) | (val << 8); - } break; case 0xa6ee: @@ -3378,9 +3229,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xaaee: if (len == 1) mach->accel.dest_x_end = (mach->accel.dest_x_end & 0x700) | val; - else { + else mach->accel.dest_x_end = val & 0x7ff; - } break; case 0xaaef: if (len == 1) @@ -3435,9 +3285,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u case 0xbeee: if (len == 1) mach->accel.src_x_end = (mach->accel.src_x_end & 0x700) | val; - else { + else mach->accel.src_x_end = val & 0x7ff; - } break; case 0xbeef: if (len == 1) @@ -3490,20 +3339,18 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u } break; case 0xceef: - if (len == 1) { + if (len == 1) mach->accel.dp_config = (mach->accel.dp_config & 0x00ff) | (val << 8); - } break; case 0xd2ee: mach->accel.patt_len = val & 0x1f; mach_log("Pattern Length = %d, val = %04x.\n", val & 0x1f, val); mach->accel.mono_pattern_enable = !!(val & 0x80); - if (len != 1) { + if (len != 1) mach->accel.patt_len_reg = val; - } else { + else mach->accel.patt_len_reg = (mach->accel.patt_len_reg & 0xff00) | val; - } break; case 0xd2ef: if (len == 1) @@ -3519,9 +3366,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("DAEE (extclipl) write val = %d\n", val); if (len == 1) dev->accel.clip_left = (dev->accel.clip_left & 0x700) | val; - else { + else dev->accel.clip_left = val & 0x7ff; - } break; case 0xdaef: if (len == 1) @@ -3532,9 +3378,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("DEEE (extclipt) write val = %d\n", val); if (len == 1) dev->accel.clip_top = (dev->accel.clip_top & 0x700) | val; - else { + else dev->accel.clip_top = val & 0x7ff; - } break; case 0xdeef: if (len == 1) @@ -3545,9 +3390,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("E2EE (extclipr) write val = %d\n", val); if (len == 1) dev->accel.multifunc[4] = (dev->accel.multifunc[4] & 0x700) | val; - else { + else dev->accel.multifunc[4] = val & 0x7ff; - } break; case 0xe2ef: if (len == 1) @@ -3558,9 +3402,8 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u mach_log("E6EE (extclipb) write val = %d\n", val); if (len == 1) dev->accel.multifunc[3] = (dev->accel.multifunc[3] & 0x700) | val; - else { + else dev->accel.multifunc[3] = val & 0x7ff; - } break; case 0xe6ef: if (len == 1) @@ -3616,53 +3459,33 @@ mach_accel_out_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, u static void mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - uint8_t old = 0; - - if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9 && port != 0x46e8 && port != 0x46e9) + if (port != 0x7aee && port != 0x7aef && port != 0x42e8 && port != 0x42e9) mach_log("[%04X:%08X]: Port CALL OUT=%04x, val=%02x.\n", CS, cpu_state.pc, port, val); switch (port) { case 0x2e8: case 0x6e9: - if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) - dev->htotal = val; - - svga_recalctimings(svga); - break; - - case 0x6e8: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) - dev->hdisped = val; - - mach_log("[%04X:%08X]: ATI 8514/A: H_DISP write 06E8 = %d, actual val=%d, set lock=%x, shadow set=%x, advfunc bit 2=%x, dispcntl=%02x, clocksel bit 0=%x.\n", CS, cpu_state.pc, dev->hdisp, ((val + 1) << 3), mach->shadow_cntl, mach->shadow_set, dev->accel.advfunc_cntl & 0x04, dev->disp_cntl & 0x60, mach->accel.clock_sel & 0x01); - mach_log("ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", port, val); - svga_recalctimings(svga); - break; - case 0xae8: - if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) - dev->hsync_start = val; - - mach_log("ATI 8514/A: (0x%04x): val=%d, hsync_start=%d.\n", port, val, (val + 1) << 3); - svga_recalctimings(svga); - break; - case 0xee8: - if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) - dev->hsync_width = val; - - mach_log("ATI 8514/A: (0x%04x): val=%d, hsync_width=%d, hsyncpol=%02x.\n", port, val & 0x1f, ((val & 0x1f) + 1) << 3, val & 0x20); - svga_recalctimings(svga); - break; - case 0x12e8: case 0x12e9: + case 0x1ae8: + case 0x1ae9: + case 0x1ee8: + case 0x1ee9: + case 0x22e8: + case 0x42e8: + case 0x42e9: + ibm8514_accel_out(port, val, svga, 2); + break; + + case 0x6e8: /*In preparation to switch from VGA to 8514/A mode*/ if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { - WRITE8(port, dev->v_total_reg, val); - dev->v_total_reg &= 0x1fff; + dev->hdisped = val; + dev->hdisp = (dev->hdisped + 1) << 3; } + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): hdisp=0x%02x.\n", CS, cpu_state.pc, port, val); svga_recalctimings(svga); break; @@ -3672,59 +3495,13 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { WRITE8(port, dev->v_disp, val); dev->v_disp &= 0x1fff; + dev->vdisp = (dev->v_disp + 1) >> 1; } - dev->modechange = dev->accel.advfunc_cntl & 0x04; - mach->compat_mode = mach->shadow_set & 0x03; mach_log("ATI 8514/A: V_DISP write 16E8 = %d\n", dev->v_disp); mach_log("ATI 8514/A: (0x%04x): vdisp=0x%02x.\n", port, val); svga_recalctimings(svga); break; - case 0x1ae8: - case 0x1ae9: - /*In preparation to switch from VGA to 8514/A mode*/ - if (!dev->on[0] || !dev->on[1] || (mach->accel.clock_sel & 0x01)) { - WRITE8(port, dev->v_sync_start, val); - dev->v_sync_start &= 0x1fff; - } - svga_recalctimings(svga); - break; - - case 0x1ee8: - case 0x1ee9: - mach_log("ATI 8514/A: V_SYNC_WID write 1EE8 = %02x\n", val); - break; - - case 0x22e8: - dev->disp_cntl = val; - dev->interlace = !!(val & 0x10); - mach_log("ATI 8514/A: DISP_CNTL write %04x=%02x, interlace=%d.\n", port, dev->disp_cntl, dev->interlace); - break; - - case 0x42e8: - old = dev->subsys_stat; - if (val & 1) - dev->subsys_stat &= ~1; - if (val & 2) - dev->subsys_stat &= ~2; - if (val & 4) - dev->subsys_stat &= ~4; - if (val & 8) - dev->subsys_stat &= ~8; - break; - case 0x42e9: - old = dev->subsys_cntl; - dev->subsys_cntl = val; - if ((old ^ val) & 1) - dev->subsys_stat |= 1; - if ((old ^ val) & 2) - dev->subsys_stat |= 2; - if ((old ^ val) & 4) - dev->subsys_stat |= 4; - if ((old ^ val) & 8) - dev->subsys_stat |= 8; - break; - case 0x4ae8: case 0x4ae9: WRITE8(port, dev->accel.advfunc_cntl, val); @@ -3736,9 +3513,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach->ext_on[port & 1] = dev->on[port & 1]; mach32_updatemapping(mach, svga); dev->vendor_mode[port & 1] = 0; - dev->hdisp = (dev->hdisped + 1) << 3; - dev->vdisp = (dev->v_disp >> 1) + 1; - mach_log("ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", port, dev->on[port & 1], dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); + mach_log("[%04X:%08X]: ATI 8514/A: (0x%04x): ON=%d, shadow crt=%x, hdisp=%d, vdisp=%d.\n", CS, cpu_state.pc, port, dev->on[port & 1], dev->accel.advfunc_cntl & 0x04, dev->hdisp, dev->vdisp); mach_log("IBM mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); svga_recalctimings(svga); break; @@ -3762,13 +3537,14 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0xaef: WRITE8(port, mach->cursor_offset_lo_reg, val); mach->cursor_offset_lo = mach->cursor_offset_lo_reg; + dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); break; case 0xeee: case 0xeef: WRITE8(port, mach->cursor_offset_hi_reg, val); mach->cursor_offset_hi = mach->cursor_offset_hi_reg & 0x0f; - dev->hwcursor.addr = (mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2; + dev->hwcursor.addr = ((mach->cursor_offset_lo | (mach->cursor_offset_hi << 16)) << 2); dev->hwcursor.ena = !!(mach->cursor_offset_hi_reg & 0x8000); break; @@ -3817,7 +3593,7 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 else dev->ext_crt_pitch <<= 1; } - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=0x%02x.\n", port, val); svga_recalctimings(svga); break; @@ -3857,20 +3633,18 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x46ee: case 0x46ef: WRITE8(port, mach->shadow_cntl, val); - mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); break; case 0x4aee: case 0x4aef: WRITE8(port, mach->accel.clock_sel, val); dev->on[port & 1] = mach->accel.clock_sel & 0x01; - mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d.\n", port, dev->on[port & 1], val, dev->hdisp, dev->vdisp); + mach_log("ATI 8514/A: (0x%04x): ON=%d, val=%04x, hdisp=%d, vdisp=%d, val=0x%02x.\n", port, dev->on[port & 1], val, dev->hdisp, dev->vdisp, val & 0xfe); mach_log("ATI mode set %s resolution.\n", (dev->accel.advfunc_cntl & 0x04) ? "2: 1024x768" : "1: 640x480"); mach->ext_on[port & 1] = dev->on[port & 1]; vga_on = !dev->on[port & 1]; dev->vendor_mode[port & 1] = 1; - dev->hdisp = (dev->hdisped + 1) << 3; - dev->vdisp = (dev->v_disp >> 1) + 1; svga_recalctimings(svga); break; @@ -3889,13 +3663,13 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x5aee: case 0x5aef: WRITE8(port, mach->shadow_set, val); - mach_log("ATI 8514/A: (0x%04x) val=%04x.\n", port, val); + mach_log("ATI 8514/A: (0x%04x) val=0x%02x.\n", port, val); if ((mach->shadow_set & 0x03) == 0x00) mach_log("Primary CRT register set.\n"); else if ((mach->shadow_set & 0x03) == 0x01) - mach_log("Shadow Set 1: 640x480.\n"); + mach_log("CRT Shadow Set 1: 640x480.\n"); else if ((mach->shadow_set & 0x03) == 0x02) - mach_log("Shadow Set 2: 1024x768.\n"); + mach_log("CRT Shadow Set 2: 1024x768.\n"); break; case 0x5eee: @@ -3924,20 +3698,21 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 case 0x6eee: case 0x6eef: WRITE8(port, mach->accel.ge_offset_lo, val); - dev->accel.ge_offset = mach->accel.ge_offset_lo; + svga_recalctimings(svga); break; case 0x72ee: case 0x72ef: WRITE8(port, mach->accel.ge_offset_hi, val); - dev->accel.ge_offset = mach->accel.ge_offset_lo | (mach->accel.ge_offset_hi << 16); + mach_log("ATI 8514/A: (0x%04x) val=0x%02x, geoffset=%04x.\n", port, val, dev->accel.ge_offset); + svga_recalctimings(svga); break; case 0x76ee: case 0x76ef: WRITE8(port, mach->accel.ge_pitch, val); dev->ext_pitch = ((mach->accel.ge_pitch & 0xff) << 3); - mach_log("ATI 8514/A: (0x%04x) val=%04x, extpitch=%d.\n", port, val, dev->ext_pitch); + mach_log("ATI 8514/A: (0x%04x) val=0x%02x, extpitch=%d.\n", port, val, dev->ext_pitch); svga_recalctimings(svga); break; @@ -3973,15 +3748,14 @@ mach_accel_out_call(uint16_t port, uint8_t val, mach_t *mach, svga_t *svga, ibm8 mach_log("ATI 8514/A: (0x%04x) val=%02x.\n", port, val); svga_recalctimings(svga); } else { - if (mach->accel.ext_ge_config & 0x8080) - ati_eeprom_write(&mach->eeprom, mach->accel.ext_ge_config & 0x4040, mach->accel.ext_ge_config & 0x2020, mach->accel.ext_ge_config & 0x1010); + ati_eeprom_write(&mach->eeprom, !!(mach->accel.ext_ge_config & 0x4040), !!(mach->accel.ext_ge_config & 0x2020), !!(mach->accel.ext_ge_config & 0x1010)); } break; case 0x7eee: case 0x7eef: WRITE8(port, mach->accel.eeprom_control, val); - ati_eeprom_write(&mach->eeprom, mach->accel.eeprom_control & 8, mach->accel.eeprom_control & 2, mach->accel.eeprom_control & 1); + ati_eeprom_write(&mach->eeprom, !!(mach->accel.eeprom_control & 8), !!(mach->accel.eeprom_control & 2), !!(mach->accel.eeprom_control & 1)); mach_log("ATI 8514/A: (0x%04x) val = %04x.\n", port, val); break; @@ -4012,25 +3786,12 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in switch (port) { case 0x82e8: - case 0xc2e8: - if (len != 1) - temp = dev->accel.cur_y; - break; - case 0x86e8: - case 0xc6e8: - if (len != 1) - temp = dev->accel.cur_x; - break; - case 0x92e8: - if (len != 1) - temp = dev->test; - break; - case 0x96e8: - if (len != 1) - temp = dev->accel.maj_axis_pcnt; + case 0xc2e8: + case 0xc6e8: + temp = ibm8514_accel_in_fifo(svga, port, len); break; case 0x9ae8: @@ -4254,16 +4015,13 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0x96ee: if (len == 1) - temp = dev->accel.maj_axis_pcnt & 0xff; - else { - temp = dev->accel.maj_axis_pcnt; - if ((mach->accel.test == 0x1555) || (mach->accel.test == 0x0aaa)) - temp = mach->accel.test; - } + temp = mach->accel.test & 0xff; + else + temp = mach->accel.test; break; case 0x96ef: if (len == 1) - temp = dev->accel.maj_axis_pcnt >> 8; + temp = mach->accel.test >> 8; break; case 0xa2ee: @@ -4375,23 +4133,29 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in case 0xfaee: if (len != 1) { - if (mach->pci_bus) - temp = 0x0017; - else - temp = 0x22f7; + if ((dev->local & 0xff) >= 0x02) { + if (mach->pci_bus) + temp = 0x0017; + else + temp = 0x22f7; + } } else { - if (mach->pci_bus) - temp = 0x17; - else - temp = 0xf7; + if ((dev->local & 0xff) >= 0x02) { + if (mach->pci_bus) + temp = 0x17; + else + temp = 0xf7; + } } break; case 0xfaef: if (len == 1) { - if (mach->pci_bus) - temp = 0x00; - else - temp = 0x22; + if ((dev->local & 0xff) >= 0x02) { + if (mach->pci_bus) + temp = 0x00; + else + temp = 0x22; + } } break; @@ -4407,64 +4171,57 @@ mach_accel_in_fifo(mach_t *mach, svga_t *svga, ibm8514_t *dev, uint16_t port, in static uint8_t mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) { - uint8_t temp = 0; - uint16_t vpos = 0; - uint16_t vblankend = svga->vblankstart + svga->crtc[0x16]; + uint8_t temp = 0; + uint16_t clip_b_ibm = dev->accel.multifunc[3]; + uint16_t clip_r_ibm = dev->accel.multifunc[4]; + int16_t clip_l = dev->accel.clip_left & 0x7ff; + int16_t clip_t = dev->accel.clip_top & 0x7ff; + int16_t clip_r = dev->accel.multifunc[4] & 0x7ff; + int16_t clip_b = dev->accel.multifunc[3] & 0x7ff; + int cmd = (dev->accel.cmd >> 13); switch (port) { case 0x2e8: - vpos = dev->vc & 0x7ff; - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) - temp |= 2; - } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) - temp |= 2; - } - break; - case 0x6e8: - temp = dev->hdisped; - break; - case 0x22e8: - temp = dev->disp_cntl; - break; - case 0x26e8: - temp = dev->htotal; - break; - + case 0x26e9: case 0x2ee8: - temp = dev->subsys_cntl; - break; case 0x2ee9: - temp = 0xff; + temp = ibm8514_accel_in(port, svga); break; case 0x42e8: case 0x42e9: - vpos = dev->vc & 0x7ff; - if (vblankend > dev->v_total) { - vblankend -= dev->v_total; - if ((vpos >= svga->vblankstart) || (vpos <= vblankend)) - dev->subsys_stat |= 1; + if (dev->vc == dev->v_syncstart) + dev->subsys_stat |= 1; + + if (mach->accel.cmd_type >= 0) { + if (((dev->accel.dx) >= clip_l) && ((dev->accel.dx) <= clip_r) && ((dev->accel.dy) >= clip_t) && ((dev->accel.dy) <= clip_b)) + temp |= 2; } else { - if ((vpos >= svga->vblankstart) && (vpos <= vblankend)) - dev->subsys_stat |= 1; + if (cmd == 6) { + if (((dev->accel.dx) >= dev->accel.clip_left) && ((dev->accel.dx) <= clip_r_ibm) && ((dev->accel.dy) >= dev->accel.clip_top) && ((dev->accel.dy) <= clip_b_ibm)) + temp |= 2; + } else { + if (((dev->accel.cx) >= dev->accel.clip_left) && ((dev->accel.dx) <= clip_r_ibm) && ((dev->accel.cy) >= dev->accel.clip_top) && ((dev->accel.cy) <= clip_b_ibm)) + temp |= 2; + } } + if (!dev->force_busy) + temp |= 8; + if (port & 1) temp = 0x80; else { - temp = dev->subsys_stat | 0x80; + temp |= (dev->subsys_stat | 0x80); if (mach->accel.ext_ge_config & 0x08) temp |= ((mach->accel.ext_ge_config & 0x07) << 4); else temp |= 0x20; } - mach_log("Subsystem Status=%04x, 4ae8 shadow set=%02x.\n", temp, dev->accel.advfunc_cntl & 4); + mach_log("0x%04x read: Subsystem Status=%02x.\n", port, temp); break; /*ATI Mach8/32 specific registers*/ @@ -4478,6 +4235,11 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) READ8(port, mach->config2); break; + case 0x1aee: + case 0x1aef: + temp = 0x00; + break; + case 0x22ee: if (mach->pci_bus) temp = mach->pci_cntl_reg; @@ -4531,23 +4293,6 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) case 0x52ee: case 0x52ef: READ8(port, mach->accel.scratch0); -#ifdef ATI_8514_ULTRA - if (mach->mca_bus) { - if (!(port & 1)) { - if (svga->ext8514 != NULL) - temp = dev->pos_regs[4]; - } else { - if (svga->ext8514 != NULL) - temp = dev->pos_regs[5]; - } - } else { - if (!(port & 1)) { - if (svga->ext8514 != NULL) { - temp = 0x20 | 0x80; - } - } - } -#endif break; case 0x56ee: @@ -4574,6 +4319,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) mach->force_busy = 0; if (ati_eeprom_read(&mach->eeprom)) temp |= 0x40; + mach_log("Mach busy temp=%02x.\n", temp); break; @@ -4605,7 +4351,7 @@ mach_accel_in_call(uint16_t port, mach_t *mach, svga_t *svga, ibm8514_t *dev) default: break; } - if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9) + if (port != 0x62ee && port != 0x62ef && port != 0x42e8 && port != 0x42e9 && port != 0x02e8 && port != 0x02e9) mach_log("[%04X:%08X]: Port NORMAL IN=%04x, temp=%04x.\n", CS, cpu_state.pc, port, temp); return temp; @@ -4860,9 +4606,8 @@ mach32_decode_addr(svga_t *svga, uint32_t addr, int write) } static __inline void -mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach) +mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach, svga_t *svga) { - svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; int writemask2 = svga->writemask; int reset_wm = 0; @@ -4874,14 +4619,12 @@ mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach) cycles -= svga->monitor->mon_video_timing_write_b; if (linear) { - addr &= svga->decode_mask; - if (addr >= dev->vram_size) - return; addr &= dev->vram_mask; dev->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; dev->vram[addr] = val; return; } else { + xga_write_test(addr, val, svga); addr = mach32_decode_addr(svga, addr, 1); if (addr == 0xffffffff) return; @@ -5003,29 +4746,59 @@ mach32_write_common(uint32_t addr, uint8_t val, int linear, mach_t *mach) svga->gdcreg[8] = wm; } +#ifdef ATI_8514_ULTRA +static void +ati8514_write(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + mach32_write_common(addr, val, 0, mach, svga); +} + +static void +ati8514_writew(uint32_t addr, uint16_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + mach32_write_common(addr, val & 0xff, 0, mach, svga); + mach32_write_common(addr + 1, val >> 8, 0, mach, svga); +} + +static void +ati8514_writel(uint32_t addr, uint32_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + mach32_write_common(addr, val & 0xff, 0, mach, svga); + mach32_write_common(addr + 1, val >> 8, 0, mach, svga); + mach32_write_common(addr + 2, val >> 16, 0, mach, svga); + mach32_write_common(addr + 3, val >> 24, 0, mach, svga); +} +#endif + static void mach32_write(uint32_t addr, uint8_t val, void *priv) { mach_t *mach = (mach_t *) priv; - mach32_write_common(addr, val, 0, mach); + mach32_write_common(addr, val, 0, mach, &mach->svga); } static void mach32_writew(uint32_t addr, uint16_t val, void *priv) { mach_t *mach = (mach_t *) priv; - mach32_write_common(addr, val & 0xff, 0, mach); - mach32_write_common(addr + 1, val >> 8, 0, mach); + mach32_write_common(addr, val & 0xff, 0, mach, &mach->svga); + mach32_write_common(addr + 1, val >> 8, 0, mach, &mach->svga); } static void mach32_writel(uint32_t addr, uint32_t val, void *priv) { mach_t *mach = (mach_t *) priv; - mach32_write_common(addr, val & 0xff, 0, mach); - mach32_write_common(addr + 1, val >> 8, 0, mach); - mach32_write_common(addr + 2, val >> 16, 0, mach); - mach32_write_common(addr + 3, val >> 24, 0, mach); + mach32_write_common(addr, val & 0xff, 0, mach, &mach->svga); + mach32_write_common(addr + 1, val >> 8, 0, mach, &mach->svga); + mach32_write_common(addr + 2, val >> 16, 0, mach, &mach->svga); + mach32_write_common(addr + 3, val >> 24, 0, mach, &mach->svga); } static __inline void @@ -5036,9 +4809,6 @@ mach32_writew_linear(uint32_t addr, uint16_t val, mach_t *mach) cycles -= svga->monitor->mon_video_timing_write_w; - addr &= svga->decode_mask; - if (addr >= dev->vram_size) - return; addr &= dev->vram_mask; dev->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; *(uint16_t *) &dev->vram[addr] = val; @@ -5052,18 +4822,14 @@ mach32_writel_linear(uint32_t addr, uint32_t val, mach_t *mach) cycles -= svga->monitor->mon_video_timing_write_l; - addr &= svga->decode_mask; - if (addr >= dev->vram_size) - return; addr &= dev->vram_mask; dev->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; *(uint32_t *) &dev->vram[addr] = val; } static __inline uint8_t -mach32_read_common(uint32_t addr, int linear, mach_t *mach) +mach32_read_common(uint32_t addr, int linear, mach_t *mach, svga_t *svga) { - svga_t *svga = &mach->svga; ibm8514_t *dev = (ibm8514_t *) svga->dev8514; uint32_t latch_addr = 0; int readplane = svga->readplane; @@ -5074,12 +4840,9 @@ mach32_read_common(uint32_t addr, int linear, mach_t *mach) cycles -= svga->monitor->mon_video_timing_read_b; if (linear) { - addr &= svga->decode_mask; - if (addr >= dev->vram_size) - return 0xff; - return dev->vram[addr & dev->vram_mask]; } else { + (void) xga_read_test(addr, svga); addr = mach32_decode_addr(svga, addr, 0); if (addr == 0xffffffff) return 0xff; @@ -5153,13 +4916,52 @@ mach32_read_common(uint32_t addr, int linear, mach_t *mach) return ret; } +#ifdef ATI_8514_ULTRA +static uint8_t +ati8514_read(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + uint8_t ret; + + ret = mach32_read_common(addr, 0, mach, svga); + return ret; +} + +static uint16_t +ati8514_readw(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + uint16_t ret; + + ret = mach32_read_common(addr, 0, mach, svga); + ret |= (mach32_read_common(addr + 1, 0, mach, svga) << 8); + return ret; +} + +static uint32_t +ati8514_readl(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + mach_t *mach = (mach_t *) svga->ext8514; + uint32_t ret; + + ret = mach32_read_common(addr, 0, mach, svga); + ret |= (mach32_read_common(addr + 1, 0, mach, svga) << 8); + ret |= (mach32_read_common(addr + 2, 0, mach, svga) << 16); + ret |= (mach32_read_common(addr + 3, 0, mach, svga) << 24); + return ret; +} +#endif + static uint8_t mach32_read(uint32_t addr, void *priv) { mach_t *mach = (mach_t *) priv; uint8_t ret; - ret = mach32_read_common(addr, 0, mach); + ret = mach32_read_common(addr, 0, mach, &mach->svga); return ret; } @@ -5169,8 +4971,8 @@ mach32_readw(uint32_t addr, void *priv) mach_t *mach = (mach_t *) priv; uint16_t ret; - ret = mach32_read_common(addr, 0, mach); - ret |= (mach32_read_common(addr + 1, 0, mach) << 8); + ret = mach32_read_common(addr, 0, mach, &mach->svga); + ret |= (mach32_read_common(addr + 1, 0, mach, &mach->svga) << 8); return ret; } @@ -5180,10 +4982,10 @@ mach32_readl(uint32_t addr, void *priv) mach_t *mach = (mach_t *) priv; uint32_t ret; - ret = mach32_read_common(addr, 0, mach); - ret |= (mach32_read_common(addr + 1, 0, mach) << 8); - ret |= (mach32_read_common(addr + 2, 0, mach) << 16); - ret |= (mach32_read_common(addr + 3, 0, mach) << 24); + ret = mach32_read_common(addr, 0, mach, &mach->svga); + ret |= (mach32_read_common(addr + 1, 0, mach, &mach->svga) << 8); + ret |= (mach32_read_common(addr + 2, 0, mach, &mach->svga) << 16); + ret |= (mach32_read_common(addr + 3, 0, mach, &mach->svga) << 24); return ret; } @@ -5195,10 +4997,6 @@ mach32_readw_linear(uint32_t addr, mach_t *mach) cycles -= svga->monitor->mon_video_timing_read_w; - addr &= svga->decode_mask; - if (addr >= dev->vram_size) - return 0xffff; - return *(uint16_t *) &dev->vram[addr & dev->vram_mask]; } @@ -5210,10 +5008,6 @@ mach32_readl_linear(uint32_t addr, mach_t *mach) cycles -= svga->monitor->mon_video_timing_read_l; - addr &= svga->decode_mask; - if (addr >= dev->vram_size) - return 0xffffffff; - return *(uint32_t *) &dev->vram[addr & dev->vram_mask]; } @@ -5237,7 +5031,7 @@ mach32_ap_writeb(uint32_t addr, uint8_t val, void *priv) } else { mach_log("Linear WORDB Write=%08x, val=%02x.\n", addr, val); if (dev->on[0] || dev->on[1]) - mach32_write_common(addr, val, 1, mach); + mach32_write_common(addr, val, 1, mach, svga); else svga_write_linear(addr, val, svga); } @@ -5314,7 +5108,7 @@ mach32_ap_readb(uint32_t addr, void *priv) temp = mach_accel_inb(0x02e8 + (addr & 1) + (port_dword << 8), mach); } else { if (dev->on[0] || dev->on[1]) - temp = mach32_read_common(addr, 1, mach); + temp = mach32_read_common(addr, 1, mach, svga); else temp = svga_read_linear(addr, svga); @@ -5434,10 +5228,18 @@ mach32_updatemapping(mach_t *mach, svga_t *svga) mach->ap_size = 4; mem_mapping_disable(&mach->mmio_linear_mapping); } - if (((dev->local & 0xff) >= 0x02) && (dev->on[0] || dev->on[1]) && (mach->ext_on[0] || mach->ext_on[1]) && (dev->vendor_mode[0] || dev->vendor_mode[1])) { + if ((dev->on[0] || dev->on[1]) && (mach->ext_on[0] || mach->ext_on[1]) && (dev->vendor_mode[0] || dev->vendor_mode[1])) { mach_log("ExtON.\n"); - mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); - mem_mapping_set_p(&svga->mapping, mach); +#ifdef ATI_8514_ULTRA + if (svga->ext8514 != NULL) { + mem_mapping_set_handler(&svga->mapping, ati8514_read, ati8514_readw, ati8514_readl, ati8514_write, ati8514_writew, ati8514_writel); + mem_mapping_set_p(&svga->mapping, svga); + } else +#endif + { + mem_mapping_set_handler(&svga->mapping, mach32_read, mach32_readw, mach32_readl, mach32_write, mach32_writew, mach32_writel); + mem_mapping_set_p(&svga->mapping, mach); + } } else { mach_log("ExtOFF.\n"); mem_mapping_set_handler(&svga->mapping, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel); @@ -5459,7 +5261,7 @@ mach32_hwcursor_draw(svga_t *svga, int displine) int x_pos; int y_pos; - mach_log("BPP=%d.\n", dev->accel_bpp); + mach_log("BPP=%d, displine=%d.\n", dev->accel_bpp, displine); switch (dev->accel_bpp) { default: case 8: @@ -5534,6 +5336,7 @@ ati8514_io_set(svga_t *svga) io_sethandler(0x26e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x2ee8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x42e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); + io_sethandler(0x46e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x4ae8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x52e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); io_sethandler(0x56e8, 0x0002, ati8514_accel_inb, ati8514_accel_inw, ati8514_accel_inl, ati8514_accel_outb, ati8514_accel_outw, ati8514_accel_outl, svga); @@ -5650,6 +5453,7 @@ mach_io_set(mach_t *mach) io_sethandler(0x26e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x2ee8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x42e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0x46e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x4ae8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x52e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0x56e8, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); @@ -5747,6 +5551,7 @@ mach_io_set(mach_t *mach) io_sethandler(0xeeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf2ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xf6ee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); + io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); io_sethandler(0xfeee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); } @@ -5828,6 +5633,12 @@ ati8514_mca_write(int port, uint8_t val, void *priv) if (dev->pos_regs[2] & 0x01) mem_mapping_enable(&dev->bios_rom.mapping); } + +void +ati8514_pos_write(uint16_t port, uint8_t val, void *priv) +{ + ati8514_mca_write(port, val, priv); +} #endif static uint8_t @@ -6029,7 +5840,7 @@ mach8_init(const device_t *info) NULL); dev->vram_size = mach->memory << 10; dev->vram = calloc(dev->vram_size, 1); - dev->changedvram = calloc(dev->vram_size >> 12, 1); + dev->changedvram = calloc((dev->vram_size >> 12) + 1, 1); dev->vram_mask = dev->vram_size - 1; dev->hwcursor.cur_ysize = 64; mach->config1 = 0x20; @@ -6044,7 +5855,7 @@ mach8_init(const device_t *info) else mach->config1 |= 0x0c; mach->config1 |= 0x0400; - svga->clock_gen = device_add(&ati18811_0_device); + svga->clock_gen = device_add(&ati18811_1_device); } else if (mach->mca_bus) { video_inform(VIDEO_FLAG_TYPE_8514, &timing_mach32_mca); if (is286 && !is386) @@ -6061,11 +5872,11 @@ mach8_init(const device_t *info) else mach->config1 |= 0x0a00; mach->config2 |= 0x2000; - svga->clock_gen = device_add(&ati18811_0_device); + svga->clock_gen = device_add(&ati18811_1_device); } else { video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); mach->config1 |= 0x0400; - svga->clock_gen = device_add(&ati18811_0_device); + svga->clock_gen = device_add(&ati18811_1_device); } mem_mapping_add(&mach->mmio_linear_mapping, 0, 0, mach32_ap_readb, mach32_ap_readw, mach32_ap_readl, mach32_ap_writeb, mach32_ap_writew, mach32_ap_writel, NULL, MEM_MAPPING_EXTERNAL, mach); mem_mapping_disable(&mach->mmio_linear_mapping); @@ -6077,15 +5888,15 @@ mach8_init(const device_t *info) NULL); dev->vram_size = (1024 << 10); dev->vram = calloc(dev->vram_size, 1); - dev->changedvram = calloc(dev->vram_size >> 12, 1); + dev->changedvram = calloc((dev->vram_size >> 12) + 1, 1); dev->vram_mask = dev->vram_size - 1; video_inform(VIDEO_FLAG_TYPE_8514, &timing_gfxultra_isa); mach->config1 = 0x01 | 0x02 | 0x20 | 0x08 | 0x80; mach->config2 = 0x02; - svga->clock_gen = device_add(&ati18810_device); + svga->clock_gen = device_add(&ati18811_0_device); } - dev->bpp = 0; - svga->getclock = ics2494_getclock; + dev->bpp = 0; + svga->getclock = ics2494_getclock; dev->on[0] = 0; dev->on[1] = 0; @@ -6107,7 +5918,6 @@ mach8_init(const device_t *info) mach->cursor_col_1 = 0xff; mach->ext_cur_col_1_r = 0xff; mach->ext_cur_col_1_g = 0xff; - io_sethandler(0xfaee, 0x0002, mach_accel_inb, mach_accel_inw, mach_accel_inl, mach_accel_outb, mach_accel_outw, mach_accel_outl, mach); if (mach->vlb_bus) ati_eeprom_load(&mach->eeprom, "mach32_vlb.nvr", 1); else if (mach->mca_bus) { @@ -6134,8 +5944,6 @@ mach8_init(const device_t *info) } else ati_eeprom_load_mach8(&mach->eeprom, "mach8.nvr"); - timer_add(&svga->timer8514, ibm8514_poll, svga, 1); - return mach; } @@ -6143,8 +5951,8 @@ mach8_init(const device_t *info) void ati8514_init(svga_t *svga, void *ext8514, void *dev8514) { - mach_t *mach = (mach_t *)ext8514; - ibm8514_t *dev = (ibm8514_t *)dev8514; + mach_t *mach = (mach_t *) ext8514; + ibm8514_t *dev = (ibm8514_t *) dev8514; dev->on[0] = 0; dev->on[1] = 0; diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/vid_bt48x_ramdac.c index 91ddce9563..6b0ec300b4 100644 --- a/src/video/vid_bt48x_ramdac.c +++ b/src/video/vid_bt48x_ramdac.c @@ -420,7 +420,7 @@ bt48x_hwcursor_draw(svga_t *svga, int displine) comb = (b0 | (b1 << 1)); y_pos = displine; - x_pos = offset + svga->x_add; + x_pos = (offset + svga->x_add) & 2047; p = buffer32->line[y_pos]; if (offset >= svga->dac_hwcursor_latch.x) { diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 2ea07c3467..c58c319df9 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -70,6 +70,15 @@ static video_timings_t timing_cga = { .type = VIDEO_ISA, .write_b = 8, .write_w void cga_recalctimings(cga_t *cga); +static void +cga_update_latch(cga_t *cga) +{ + uint32_t lp_latch = cga->displine * cga->crtc[1]; + + cga->crtc[0x10] = (lp_latch >> 8) & 0x3f; + cga->crtc[0x11] = lp_latch & 0xff; +} + void cga_out(uint16_t addr, uint8_t val, void *priv) { @@ -87,7 +96,7 @@ cga_out(uint16_t addr, uint8_t val, void *priv) old = cga->crtc[cga->crtcreg]; cga->crtc[cga->crtcreg] = val & crtcmask[cga->crtcreg]; if (old != val) { - if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x10)) { + if ((cga->crtcreg < 0xe) || (cga->crtcreg > 0x11)) { cga->fullchange = changeframecount; cga_recalctimings(cga); } @@ -111,6 +120,17 @@ cga_out(uint16_t addr, uint8_t val, void *priv) cga_recalctimings(cga); return; + case 0x3DB: + if (cga->lp_strobe == 1) + cga->lp_strobe = 0; + return; + case 0x3DC: + if (cga->lp_strobe == 0) { + cga->lp_strobe = 1; + cga_update_latch(cga); + } + return; + default: break; } @@ -119,8 +139,7 @@ cga_out(uint16_t addr, uint8_t val, void *priv) uint8_t cga_in(uint16_t addr, void *priv) { - const cga_t *cga = (cga_t *) priv; - + cga_t *cga = (cga_t *) priv; uint8_t ret = 0xff; if ((addr >= 0x3d0) && (addr <= 0x3d7)) @@ -137,6 +156,17 @@ cga_in(uint16_t addr, void *priv) ret = cga->cgastat; break; + case 0x3DB: + if (cga->lp_strobe == 1) + cga->lp_strobe = 0; + break; + case 0x3DC: + if (cga->lp_strobe == 0) { + cga->lp_strobe = 1; + cga_update_latch(cga); + } + break; + default: break; } diff --git a/src/video/vid_chips_69000.c b/src/video/vid_chips_69000.c index d91ab1a8b7..5d41dc4a79 100644 --- a/src/video/vid_chips_69000.c +++ b/src/video/vid_chips_69000.c @@ -156,11 +156,13 @@ typedef struct chips_69000_t { rom_t bios_rom; - void* i2c_ddc, *ddc; + void *i2c, *ddc; uint8_t st01; } chips_69000_t; +static chips_69000_t *reset_state = NULL; + /* TODO: Probe timings on real hardware. */ static video_timings_t timing_chips = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 1, .read_b = 10, .read_w = 10, .read_l = 10 }; @@ -777,7 +779,7 @@ chips_69000_recalctimings(svga_t *svga) if (!(chips->ext_regs[0x81] & 0x10)) svga->htotal += 5; - + svga->hblank_end_val = ((svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00)) | (svga->crtc[0x3c] & 0b11000000); svga->hblank_end_mask = 0xff; @@ -980,7 +982,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } - + break; } } @@ -1018,7 +1020,7 @@ chips_69000_process_pixel(chips_69000_t* chips, uint32_t pixel) if (!!(color_key == dest_pixel) == !!(chips->bitblt_running.bitblt.bitblt_control & (1 << 16))) { return; } - + break; } } @@ -1191,7 +1193,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) chips->bitblt_running.mono_bytes_pitch = ((chips->bitblt_running.actual_destination_width + chips->bitblt_running.bitblt.monochrome_source_left_clip + 63) & ~63) / 8; } } - + return; } @@ -1273,7 +1275,7 @@ chips_69000_setup_bitblt(chips_69000_t* chips) do { uint32_t pixel = 0; uint32_t source_addr = chips->bitblt_running.bitblt.source_addr + (chips->bitblt_running.y * chips->bitblt.source_span) + (chips->bitblt_running.x * chips->bitblt_running.bytes_per_pixel); - + switch (chips->bitblt_running.bytes_per_pixel) { case 1: /* 8 bits-per-pixel. */ { @@ -1423,7 +1425,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { source_pixel |= (chips->bitblt_running.bytes_port[1] << 8); if (chips->bitblt_running.bytes_per_pixel >= 3) source_pixel |= (chips->bitblt_running.bytes_port[2] << 16); - + chips->bitblt_running.bytes_in_line_written += chips->bitblt_running.bytes_per_pixel; chips_69000_process_pixel(chips, source_pixel); @@ -1446,7 +1448,7 @@ chips_69000_bitblt_write(chips_69000_t* chips, uint8_t data) { chips->bitblt_running.count_x = 0; chips->bitblt_running.x = 0; - + if (chips->bitblt_running.count_y >= chips->bitblt_running.actual_destination_height) { chips_69000_bitblt_interrupt(chips); return; @@ -1497,10 +1499,10 @@ chips_69000_read_ext_reg(chips_69000_t* chips) { val = chips->ext_regs[index]; if (!(chips->ext_regs[0x62] & 0x8)) - val = (val & ~8) | (i2c_gpio_get_scl(chips->i2c_ddc) << 3); - + val = (val & ~8) | (i2c_gpio_get_scl(chips->i2c) << 3); + if (!(chips->ext_regs[0x62] & 0x4)) - val = (val & ~4) | (i2c_gpio_get_sda(chips->i2c_ddc) << 2); + val = (val & ~4) | (i2c_gpio_get_sda(chips->i2c) << 2); break; } @@ -1560,14 +1562,14 @@ chips_69000_write_ext_reg(chips_69000_t* chips, uint8_t val) if (chips->ext_regs[0x62] & 0x8) scl = !!(val & 8); else - scl = i2c_gpio_get_scl(chips->i2c_ddc); - + scl = i2c_gpio_get_scl(chips->i2c); + if (chips->ext_regs[0x62] & 0x4) sda = !!(val & 4); else - scl = i2c_gpio_get_sda(chips->i2c_ddc); - - i2c_gpio_set(chips->i2c_ddc, scl, sda); + scl = i2c_gpio_get_sda(chips->i2c); + + i2c_gpio_set(chips->i2c, scl, sda); chips->ext_regs[chips->ext_index] = val & 0x9F; break; @@ -1742,7 +1744,7 @@ chips_69000_out(uint16_t addr, uint8_t val, void *p) case 0x3B7: case 0x3D7: return chips_69000_write_ext_reg(chips, val); - + } svga_out(addr, val, svga); } @@ -1901,17 +1903,15 @@ chips_69000_pci_write(int func, int addr, uint8_t val, void *p) if (chips->pci_conf_status & PCI_COMMAND_MEM) { mem_mapping_enable(&chips->svga.mapping); if (chips->linear_mapping.base) - mem_mapping_enable(&chips->linear_mapping); + mem_mapping_set_addr(&chips->linear_mapping, chips->linear_mapping.base, (1 << 24)); } break; } case 0x13: { - if (!chips->linear_mapping.enable) { - chips->linear_mapping.base = val << 24; - break; - } - mem_mapping_set_addr(&chips->linear_mapping, val << 24, (1 << 24)); + chips->linear_mapping.base = val << 24; + if (chips->linear_mapping.base) + mem_mapping_set_addr(&chips->linear_mapping, chips->linear_mapping.base, (1 << 24)); break; } case 0x3c: @@ -2093,7 +2093,7 @@ chips_69000_writeb_mmio(uint32_t addr, uint8_t val, chips_69000_t* chips) chips->mem_regs_b[addr & 0xF] = val; break; } - + } chips->mem_regs_b[addr & 0xF] = val; break; @@ -2213,7 +2213,7 @@ chips_69000_readw_linear(uint32_t addr, void *p) if (addr & 0x800000) { if (addr & 0x400000) return bswap16(chips_69000_readw_mmio(addr, chips)); - + return bswap16(svga_readw_linear(addr & 0x1FFFFF, p)); } @@ -2232,7 +2232,7 @@ chips_69000_readl_linear(uint32_t addr, void *p) if (addr & 0x800000) { if (addr & 0x400000) return bswap32(chips_69000_readl_mmio(addr, chips)); - + return bswap32(svga_readl_linear(addr & 0x1FFFFF, p)); } @@ -2290,7 +2290,7 @@ chips_69000_vblank_start(svga_t *svga) chips_69000_t *chips = (chips_69000_t *) svga->priv; chips->mem_regs[1] |= 1 << 14; chips->svga.crtc[0x40] &= ~0x80; - + chips_69000_interrupt(chips); } @@ -2307,13 +2307,13 @@ chips_69000_hwcursor_draw_64x64(svga_t *svga, int displine) dat[1] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr])); dat[0] = bswap64(*(uint64_t *) (&svga->vram[svga->hwcursor_latch.addr + 8])); svga->hwcursor_latch.addr += 16; - + for (uint8_t x = 0; x < 64; x++) { if (!(dat[1] & (1ULL << 63))) svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] = (dat[0] & (1ULL << 63)) ? svga_lookup_lut_ram(svga, chips->cursor_pallook[5]) : svga_lookup_lut_ram(svga, chips->cursor_pallook[4]); else if (dat[0] & (1ULL << 63)) svga->monitor->target_buffer->line[displine][(offset + svga->x_add) & 2047] ^= 0xffffff; - + offset++; dat[0] <<= 1; dat[1] <<= 1; @@ -2430,14 +2430,48 @@ chips_69000_line_compare(svga_t* svga) if (chips->ext_regs[0x81] & 0xF) { return 0; } - + return 1; } +static void +chips_69000_disable_handlers(chips_69000_t *chips) +{ + io_removehandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); + + mem_mapping_disable(&chips->linear_mapping); + mem_mapping_disable(&chips->svga.mapping); + if (!chips->on_board) + mem_mapping_disable(&chips->bios_rom.mapping); + + /* Save all the mappings and the timers because they are part of linked lists. */ + reset_state->linear_mapping = chips->linear_mapping; + reset_state->svga.mapping = chips->svga.mapping; + reset_state->bios_rom.mapping = chips->bios_rom.mapping; + + reset_state->decrement_timer = chips->decrement_timer; + reset_state->svga.timer = chips->svga.timer; + reset_state->svga.timer8514 = chips->svga.timer8514; +} + +static void +chips_69000_reset(void *priv) +{ + chips_69000_t *chips = (chips_69000_t *) priv; + + if (reset_state != NULL) { + chips_69000_disable_handlers(chips); + reset_state->slot = chips->slot; + + *chips = *reset_state; + } +} + static void * chips_69000_init(const device_t *info) { chips_69000_t *chips = calloc(1, sizeof(chips_69000_t)); + reset_state = calloc(1, sizeof(chips_69000_t)); /* Appears to have an odd VBIOS size. */ if (!info->local) { @@ -2450,18 +2484,16 @@ chips_69000_init(const device_t *info) svga_init(info, &chips->svga, chips, 1 << 21, /*2048kb*/ chips_69000_recalctimings, chips_69000_in, chips_69000_out, - NULL, + chips_69000_hwcursor_draw, NULL); io_sethandler(0x03c0, 0x0020, chips_69000_in, NULL, NULL, chips_69000_out, NULL, NULL, chips); - pci_add_card(PCI_ADD_VIDEO, chips_69000_pci_read, chips_69000_pci_write, chips, &chips->slot); + pci_add_card(info->local ? PCI_ADD_VIDEO : PCI_ADD_NORMAL, chips_69000_pci_read, chips_69000_pci_write, chips, &chips->slot); chips->svga.bpp = 8; chips->svga.miscout = 1; - chips->svga.recalctimings_ex = chips_69000_recalctimings; chips->svga.vblank_start = chips_69000_vblank_start; - chips->svga.hwcursor_draw = chips_69000_hwcursor_draw; chips->svga.getclock = chips_69000_getclock; chips->svga.conv_16to32 = chips_69000_conv_16to32; chips->svga.line_compare = chips_69000_line_compare; @@ -2471,17 +2503,19 @@ chips_69000_init(const device_t *info) chips->quit = 0; chips->engine_active = 0; chips->on_board = !!(info->local); - + chips->svga.packed_chain4 = 1; timer_add(&chips->decrement_timer, chips_69000_decrement_timer, chips, 0); timer_on_auto(&chips->decrement_timer, 1000000. / 2000.); - chips->i2c_ddc = i2c_gpio_init("c&t_69000_mga"); - chips->ddc = ddc_init(i2c_gpio_get_bus(chips->i2c_ddc)); - + chips->i2c = i2c_gpio_init("ddc_chips_69000"); + chips->ddc = ddc_init(i2c_gpio_get_bus(chips->i2c)); + chips->flat_panel_regs[0x01] = 1; + *reset_state = *chips; + return chips; } @@ -2500,9 +2534,12 @@ chips_69000_close(void *p) // thread_set_event(chips->fifo_event); // thread_wait(chips->accel_thread); ddc_close(chips->ddc); - i2c_gpio_close(chips->i2c_ddc); + i2c_gpio_close(chips->i2c); svga_close(&chips->svga); + free(reset_state); + reset_state = NULL; + free(chips); } @@ -2519,17 +2556,17 @@ chips_69000_force_redraw(void *p) { chips_69000_t *chips = (chips_69000_t *) p; - chips->svga.fullchange = changeframecount; + chips->svga.fullchange = chips->svga.monitor->mon_changeframecount; } const device_t chips_69000_device = { .name = "Chips & Technologies B69000", - .internal_name = "c&t_69000", + .internal_name = "chips_69000", .flags = DEVICE_PCI, .local = 0, .init = chips_69000_init, .close = chips_69000_close, - .reset = NULL, + .reset = chips_69000_reset, { .available = chips_69000_available }, .speed_changed = chips_69000_speed_changed, .force_redraw = chips_69000_force_redraw, @@ -2537,13 +2574,13 @@ const device_t chips_69000_device = { }; const device_t chips_69000_onboard_device = { - .name = "Chips & Technologies B69000 (onboard)", - .internal_name = "c&t_69000_onboard", + .name = "Chips & Technologies B69000 On-Board", + .internal_name = "chips_69000_onboard", .flags = DEVICE_PCI, .local = 1, .init = chips_69000_init, .close = chips_69000_close, - .reset = NULL, + .reset = chips_69000_reset, { .available = chips_69000_available }, .speed_changed = chips_69000_speed_changed, .force_redraw = chips_69000_force_redraw, diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index bf27a700aa..01210a9d9b 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -37,6 +37,7 @@ #include <86box/video.h> #include <86box/i2c.h> #include <86box/vid_ddc.h> +#include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/plat_fallthrough.h> @@ -2195,6 +2196,8 @@ gd54xx_write(uint32_t addr, uint8_t val, void *priv) return; } + xga_write_test(addr, val, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; svga_write_linear(addr, val, svga); @@ -2212,6 +2215,9 @@ gd54xx_writew(uint32_t addr, uint16_t val, void *priv) return; } + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; @@ -2237,6 +2243,11 @@ gd54xx_writel(uint32_t addr, uint32_t val, void *priv) return; } + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + xga_write_test(addr + 2, val >> 16, svga); + xga_write_test(addr + 3, val >> 24, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; @@ -2762,6 +2773,8 @@ gd54xx_read(uint32_t addr, void *priv) if (gd54xx->countminusone && gd54xx->blt.ms_is_dest && !(gd54xx->blt.status & CIRRUS_BLT_PAUSED)) return gd54xx_mem_sys_dest_read(gd54xx, 0); + (void) xga_read_test(addr, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_read_linear(addr, svga); @@ -2780,6 +2793,9 @@ gd54xx_readw(uint32_t addr, void *priv) return ret; } + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readw_linear(addr, svga); @@ -2800,6 +2816,11 @@ gd54xx_readl(uint32_t addr, void *priv) return ret; } + (void) xga_read_test(addr, svga); + (void) xga_read_test(addr + 1, svga); + (void) xga_read_test(addr + 2, svga); + (void) xga_read_test(addr + 3, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + svga->extra_banks[(addr >> 15) & 1]; return svga_readl_linear(addr, svga); @@ -3826,6 +3847,16 @@ cl_pci_read(UNUSED(int func), int addr, void *priv) ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? ((gd54xx->vgablt_base >> 24) & 0xff) : 0x00; break; + case 0x2c: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? gd54xx->bios_rom.rom[0x7ffc] : 0x00; + break; + case 0x2d: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? gd54xx->bios_rom.rom[0x7ffd] : 0x00; + break; + case 0x2e: + ret = (svga->crtc[0x27] == CIRRUS_ID_CLGD5480) ? gd54xx->bios_rom.rom[0x7ffe] : 0x00; + break; + case 0x30: ret = (gd54xx->pci_regs[0x30] & 0x01); /*BIOS ROM address*/ break; diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index 8f995117c8..5a4f100dfe 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -54,11 +54,18 @@ enum { EGA_TSENG }; +enum { + EGA_TYPE_IBM = 0, + EGA_TYPE_OTHER = 1, + EGA_TYPE_COMPAQ = 2 +}; + static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static uint8_t ega_rotate[8][256]; +static int active = 0; static uint32_t pallook16[256]; static uint32_t pallook64[256]; -static int ega_type = 0; +static int ega_type = EGA_TYPE_IBM; static int old_overscan_color = 0; /* 3C2 controls default mode on EGA. On VGA, it determines monitor type (mono or colour): @@ -149,6 +156,25 @@ ega_out(uint16_t addr, uint8_t val, void *priv) if (!(val & 1)) io_sethandler(0x03a0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); ega_recalctimings(ega); + if ((ega_type == EGA_TYPE_COMPAQ) && !(val & 0x02)) + mem_mapping_disable(&ega->mapping); + else switch (ega->gdcreg[6] & 0xc) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x10000); + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&ega->mapping, 0xb0000, 0x08000); + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&ega->mapping, 0xb8000, 0x08000); + break; + + default: + break; + } break; case 0x3c4: ega->seqaddr = val; @@ -180,7 +206,7 @@ ega_out(uint16_t addr, uint8_t val, void *priv) } break; case 0x3c6: - if (ega_type == 2) + if (ega_type == EGA_TYPE_COMPAQ) ega->ctl_mode = val; break; case 0x3ce: @@ -201,7 +227,9 @@ ega_out(uint16_t addr, uint8_t val, void *priv) ega->chain2_read = val & 0x10; break; case 6: - switch (val & 0xc) { + if ((ega_type == EGA_TYPE_COMPAQ) && !(ega->miscout & 0x02)) + mem_mapping_disable(&ega->mapping); + else switch (val & 0xc) { case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&ega->mapping, 0xa0000, 0x20000); break; @@ -295,47 +323,47 @@ ega_in(uint16_t addr, void *priv) break; case 0x3c0: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->attraddr | ega->attr_palette_enable; break; case 0x3c1: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->attrregs[ega->attraddr]; break; case 0x3c2: ret = (egaswitches & (8 >> egaswitchread)) ? 0x10 : 0x00; break; case 0x3c4: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->seqaddr; break; case 0x3c5: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->seqregs[ega->seqaddr & 0xf]; break; case 0x3c6: - if (ega_type == 2) + if (ega_type == EGA_TYPE_COMPAQ) ret = ega->ctl_mode; break; case 0x3c8: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = 2; break; case 0x3cc: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->miscout; break; case 0x3ce: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->gdcaddr; break; case 0x3cf: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->gdcreg[ega->gdcaddr & 0xf]; break; case 0x3d0: case 0x3d4: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->crtcreg; break; case 0x3d1: @@ -349,28 +377,28 @@ ega_in(uint16_t addr, void *priv) break; case 0x10: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; else ret = ega->light_pen >> 8; break; case 0x11: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; else ret = ega->light_pen & 0xff; break; default: - if (ega_type == 1) + if (ega_type == EGA_TYPE_OTHER) ret = ega->crtc[ega->crtcreg]; break; } break; case 0x3da: ega->attrff = 0; - if (ega_type == 2) { + if (ega_type == EGA_TYPE_COMPAQ) { ret = ega->stat & 0xcf; switch ((ega->attrregs[0x12] >> 4) & 0x03) { case 0x00: @@ -466,7 +494,7 @@ ega_recalctimings(ega_t *ega) ega->linedbl = ega->crtc[9] & 0x80; ega->rowcount = ega->crtc[9] & 0x1f; - if (ega_type == 2) { + if (ega_type == EGA_TYPE_COMPAQ) { color = (ega->miscout & 1); clksel = ((ega->miscout & 0xc) >> 2); @@ -587,9 +615,16 @@ ega_recalctimings(ega_t *ega) if (ega->dispofftime < TIMER_USEC) ega->dispofftime = TIMER_USEC; - ega->dot_time = (uint64_t) (ega->dot_clock); - if (ega->dot_time < TIMER_USEC) - ega->dot_time = TIMER_USEC; + if (ega_type == EGA_TYPE_COMPAQ) { + ega->dot_time = (uint64_t) (ega->dot_clock); + if (ega->dot_time < TIMER_USEC) + ega->dot_time = TIMER_USEC; + timer_disable(&ega->dot_timer); + timer_set_delay_u64(&ega->dot_timer, ega->dot_time); + ega->cca = 0; + active = 1; + ega->dot = 0; + } ega_recalc_remap_func(ega); } @@ -616,14 +651,13 @@ ega_dot_poll(void *priv) uint32_t addr; int drawcursor; uint32_t charaddr; - static int fg; - static int bg; - static uint32_t dat; + static int fg = 0; + static int bg = 0; + static uint32_t dat = 0x00000000; + static int cclock = 0; static int disptime; static int _dispontime; static int _dispofftime; - static int cclock = 0; - static int active = 0; if (ega->seqregs[1] & 8) { disptime = ((ega->crtc[0] + 2) << 1); @@ -1278,6 +1312,10 @@ ega_read(uint32_t addr, void *priv) temp4 &= (ega->colournocare & 8) ? 0xff : 0; return ~(temp | temp2 | temp3 | temp4); } + + if ((ega_type == EGA_TYPE_COMPAQ) && (ega->gdcreg[4] & 0x04)) + return 0xff; + return ega->vram[addr | readplane]; } @@ -1392,7 +1430,7 @@ ega_init(ega_t *ega, int monitor_type, int is_mono) ega->crtc[6] = 255; timer_add(&ega->timer, ega_poll, ega, 1); - if (ega_type == 2) + if (ega_type == EGA_TYPE_COMPAQ) timer_add(&ega->dot_timer, ega_dot_poll, ega, 1); } @@ -1412,11 +1450,11 @@ ega_standalone_init(const device_t *info) ega->y_add = 14; if ((info->local == EGA_IBM) || (info->local == EGA_ISKRA) || (info->local == EGA_TSENG)) - ega_type = 0; + ega_type = EGA_TYPE_IBM; else if (info->local == EGA_COMPAQ) - ega_type = 2; + ega_type = EGA_TYPE_COMPAQ; else - ega_type = 1; + ega_type = EGA_TYPE_OTHER; ega->actual_type = info->local; ega->chipset = 0; @@ -1466,6 +1504,8 @@ ega_standalone_init(const device_t *info) ega->vrammask = ega->vram_limit - 1; mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); + if (ega_type == EGA_TYPE_COMPAQ) + mem_mapping_disable(&ega->mapping); io_sethandler(0x03c0, 0x0020, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); if (ega->chipset) { diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index 0cb1216ad8..fe26325743 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -201,7 +201,8 @@ ega_render_graphics(ega_t *ega) const bool crtcreset = ((ega->crtc[0x17] & 0x80) == 0); const bool seq9dot = ((ega->seqregs[1] & 1) == 0); const bool seqoddeven = ((ega->seqregs[1] & 4) != 0); - const uint8_t blinkmask = (attrblink && blinked ? 0x8 : 0x0); + const uint8_t blinkmask = (attrblink ? 0x8 : 0x0); + const uint8_t blinkval = (attrblink && blinked ? 0x8 : 0x0); uint32_t *p = &buffer32->line[ega->displine + ega->y_add][ega->x_add]; const int dwshift = doublewidth ? 1 : 0; const int dotwidth = 1 << dwshift; @@ -254,8 +255,14 @@ ega_render_graphics(ega_t *ega) uint8_t dat = (edatlookup[(edat[0] >> inshift) & 3][(edat[1] >> inshift) & 3]) | (edatlookup[(edat[2] >> inshift) & 3][(edat[3] >> inshift) & 3] << 2); // FIXME: Confirm blink behaviour is actually XOR on real hardware - uint32_t p0 = ega->pallook[ega->egapal[((dat >> 4) & ega->plane_mask) ^ blinkmask]]; - uint32_t p1 = ega->pallook[ega->egapal[(dat & ega->plane_mask) ^ blinkmask]]; + uint32_t c0 = (dat >> 4) & 0xF; + uint32_t c1 = dat & 0xF; + c0 = ((c0 & ega->plane_mask & ~blinkmask) | + ((c0 | ~ega->plane_mask) & blinkmask & blinkval)) ^ blinkmask; + c1 = ((c1 & ega->plane_mask & ~blinkmask) | + ((c1 | ~ega->plane_mask) & blinkmask & blinkval)) ^ blinkmask; + uint32_t p0 = ega->pallook[ega->egapal[c0]]; + uint32_t p1 = ega->pallook[ega->egapal[c1]]; for (int subx = 0; subx < dotwidth; subx++) p[outoffs + subx] = p0; for (int subx = 0; subx < dotwidth; subx++) diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 583487c5fe..0ac7050f47 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -125,15 +125,6 @@ et4000_in(uint16_t addr, void *priv) addr ^= 0x60; switch (addr) { - case 0x3c2: - if (dev->type == ET4000_TYPE_MCA) { - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - return 0; - else - return 0x10; - } - break; - case 0x3c5: if ((svga->seqaddr & 0xf) == 7) return svga->seqregs[svga->seqaddr & 0xf] | 4; @@ -145,6 +136,7 @@ et4000_in(uint16_t addr, void *priv) case 0x3c9: if (dev->type >= ET4000_TYPE_ISA) return sc1502x_ramdac_in(addr, svga->ramdac, svga); + break; case 0x3cd: /*Banking*/ return dev->banking; @@ -769,12 +761,16 @@ et4000_mca_write(int port, uint8_t val, void *priv) /* Save the MCA register value. */ et4000->pos_regs[port & 7] = val; + mem_mapping_disable(&et4000->bios_rom.mapping); + if (et4000->pos_regs[2] & 1) + mem_mapping_enable(&et4000->bios_rom.mapping); } static uint8_t et4000_mca_feedb(UNUSED(void *priv)) { - return 1; + et4000_t *et4000 = (et4000_t *) priv; + return et4000->pos_regs[2] & 1; } static void * @@ -888,7 +884,10 @@ et4000_init(const device_t *info) dev->vram_mask = dev->vram_size - 1; rom_init(&dev->bios_rom, fn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + + if (dev->type == ET4000_TYPE_MCA) + mem_mapping_disable(&dev->bios_rom.mapping); dev->svga.translate_address = get_et4000_addr; diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index 213cf9ed4b..7d868a63ba 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -33,6 +33,7 @@ #include <86box/rom.h> #include <86box/device.h> #include <86box/video.h> +#include <86box/vid_xga.h> #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> #include <86box/plat_fallthrough.h> @@ -1217,6 +1218,8 @@ ht216_write(uint32_t addr, uint8_t val, void *priv) svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + xga_write_test(addr, val, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; @@ -1238,6 +1241,9 @@ ht216_writew(uint32_t addr, uint16_t val, void *priv) svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; @@ -1261,6 +1267,11 @@ ht216_writel(uint32_t addr, uint32_t val, void *priv) svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + xga_write_test(addr, val, svga); + xga_write_test(addr + 1, val >> 8, svga); + xga_write_test(addr + 2, val >> 16, svga); + xga_write_test(addr + 3, val >> 24, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->write_banks[(addr >> 15) & 1]; @@ -1422,9 +1433,11 @@ static uint8_t ht216_read(uint32_t addr, void *priv) { ht216_t *ht216 = (ht216_t *) priv; - const svga_t *svga = &ht216->svga; + svga_t *svga = &ht216->svga; uint32_t prev_addr = addr; + (void) xga_read_test(addr, svga); + addr &= svga->banked_mask; addr = (addr & 0x7fff) + ht216->read_banks[(addr >> 15) & 1]; diff --git a/src/video/vid_ics2494.c b/src/video/vid_ics2494.c index 309d07966b..e85b4539ef 100644 --- a/src/video/vid_ics2494.c +++ b/src/video/vid_ics2494.c @@ -56,6 +56,7 @@ ics2494_getclock(int clock, void *priv) if (clock > 15) clock = 15; + ics2494_log("Clock=%d, freq=%f.\n", clock, ics2494->freq[clock]); return ics2494->freq[clock]; } @@ -68,60 +69,60 @@ ics2494_init(const device_t *info) switch (info->local) { case 10: /* ATI 18810 for ATI 28800 */ - ics2494->freq[0x0] = 30240000.0; - ics2494->freq[0x1] = 32000000.0; - ics2494->freq[0x2] = 37500000.0; - ics2494->freq[0x3] = 39000000.0; - ics2494->freq[0x4] = 42954000.0; - ics2494->freq[0x5] = 48771000.0; - ics2494->freq[0x6] = 16657000.0; - ics2494->freq[0x7] = 36000000.0; - ics2494->freq[0x8] = 40000000.0; - ics2494->freq[0x9] = 56644000.0; - ics2494->freq[0xa] = 75000000.0; - ics2494->freq[0xb] = 65000000.0; - ics2494->freq[0xc] = 50350000.0; - ics2494->freq[0xd] = 56640000.0; - ics2494->freq[0xe] = 28322000.0; - ics2494->freq[0xf] = 44900000.0; + ics2494->freq[0x0] = 42954000.0; + ics2494->freq[0x1] = 48771000.0; + ics2494->freq[0x2] = 0.0; + ics2494->freq[0x3] = 36000000.0; + ics2494->freq[0x4] = 50350000.0; + ics2494->freq[0x5] = 56640000.0; + ics2494->freq[0x6] = 0.0; + ics2494->freq[0x7] = 44900000.0; + ics2494->freq[0x8] = 30240000.0; + ics2494->freq[0x9] = 32000000.0; + ics2494->freq[0xa] = 37500000.0; + ics2494->freq[0xb] = 39000000.0; + ics2494->freq[0xc] = 40000000.0; + ics2494->freq[0xd] = 56644000.0; + ics2494->freq[0xe] = 75000000.0; + ics2494->freq[0xf] = 65000000.0; break; case 110: /* ATI 18811-0 for ATI Mach32 */ - ics2494->freq[0x0] = 30240000.0; - ics2494->freq[0x1] = 32000000.0; - ics2494->freq[0x2] = 110000000.0; - ics2494->freq[0x3] = 80000000.0; - ics2494->freq[0x4] = 42954000.0; - ics2494->freq[0x5] = 48771000.0; - ics2494->freq[0x6] = 92400000.0; - ics2494->freq[0x7] = 36000000.0; - ics2494->freq[0x8] = 39910000.0; - ics2494->freq[0x9] = 44900000.0; - ics2494->freq[0xa] = 75000000.0; - ics2494->freq[0xb] = 65000000.0; - ics2494->freq[0xc] = 50350000.0; - ics2494->freq[0xd] = 56640000.0; - ics2494->freq[0xe] = 0.0; - ics2494->freq[0xf] = 44900000.0; + ics2494->freq[0x0] = 42954000.0; + ics2494->freq[0x1] = 48771000.0; + ics2494->freq[0x2] = 92400000.0; + ics2494->freq[0x3] = 36000000.0; + ics2494->freq[0x4] = 50350000.0; + ics2494->freq[0x5] = 56640000.0; + ics2494->freq[0x6] = 0.0; + ics2494->freq[0x7] = 44900000.0; + ics2494->freq[0x8] = 30240000.0; + ics2494->freq[0x9] = 32000000.0; + ics2494->freq[0xa] = 110000000.0; + ics2494->freq[0xb] = 80000000.0; + ics2494->freq[0xc] = 39910000.0; + ics2494->freq[0xd] = 44900000.0; + ics2494->freq[0xe] = 75000000.0; + ics2494->freq[0xf] = 65000000.0; break; case 111: /* ATI 18811-1 for ATI Mach32 MCA */ - ics2494->freq[0x0] = 135000000.0; - ics2494->freq[0x1] = 32000000.0; - ics2494->freq[0x2] = 110000000.0; - ics2494->freq[0x3] = 80000000.0; - ics2494->freq[0x4] = 100000000.0; - ics2494->freq[0x5] = 126000000.0; - ics2494->freq[0x6] = 92400000.0; - ics2494->freq[0x7] = 36000000.0; - ics2494->freq[0x8] = 39910000.0; - ics2494->freq[0x9] = 44900000.0; - ics2494->freq[0xa] = 75000000.0; - ics2494->freq[0xb] = 65000000.0; - ics2494->freq[0xc] = 50350000.0; - ics2494->freq[0xd] = 56640000.0; - ics2494->freq[0xe] = 0.0; - ics2494->freq[0xf] = 44900000.0; + ics2494->freq[0x0] = 100000000.0; + ics2494->freq[0x1] = 126000000.0; + ics2494->freq[0x2] = 92400000.0; + ics2494->freq[0x3] = 36000000.0; + ics2494->freq[0x4] = 50350000.0; + ics2494->freq[0x5] = 56640000.0; + ics2494->freq[0x6] = 0.0; + ics2494->freq[0x7] = 44900000.0; + ics2494->freq[0x8] = 135000000.0; + ics2494->freq[0x9] = 32000000.0; + ics2494->freq[0xa] = 110000000.0; + ics2494->freq[0xb] = 80000000.0; + ics2494->freq[0xc] = 39910000.0; + ics2494->freq[0xd] = 44900000.0; + ics2494->freq[0xe] = 75000000.0; + ics2494->freq[0xf] = 65000000.0; break; case 305: /* ICS2494A(N)-205 for S3 86C924 */ diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c index fdbb2e4118..1bdbecdf61 100644 --- a/src/video/vid_mga.c +++ b/src/video/vid_mga.c @@ -491,7 +491,7 @@ typedef struct mystique_t { struct { - uint8_t funcnt, stylelen, + uint8_t funcnt : 7, stylelen, dmamod; int16_t fxleft, fxright, @@ -505,7 +505,7 @@ typedef struct mystique_t { ta_key, ta_mask, lastpix_r, lastpix_g, lastpix_b, highv_line, beta, dither, err, k1, k2; - int pattern[8][16]; + bool pattern[8][16]; uint32_t dwgctrl, dwgctrl_running, bcol, fcol, pitch, plnwt, ybot, ydstorg, @@ -3885,7 +3885,6 @@ blit_iload_iload(mystique_t *mystique, uint32_t data, int size) data64 = mystique->dwgreg.iload_rem_data | ((uint64_t) data << mystique->dwgreg.iload_rem_count); while (size >= 32) { int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; - pclog("maccess = 0x%X\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { @@ -4377,15 +4376,20 @@ blit_line(mystique_t *mystique, int closed, int autoline) uint32_t old_dst; int x = mystique->dwgreg.xdst; int z_write; + int pattern_x, pattern_y; + bool transc = !!(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC); switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { case DWGCTRL_ATYPE_RSTR: case DWGCTRL_ATYPE_RPL: while (mystique->dwgreg.length >= 0) { if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + pattern_y = ((mystique->dwgreg.funcnt % (mystique->dwgreg.stylelen + 1)) >> 4) & 0x7; + pattern_x = (mystique->dwgreg.funcnt % (mystique->dwgreg.stylelen + 1)) & 0xf; + if (!transc || (transc && (mystique->dwgreg.pattern[pattern_y][pattern_x]))) switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { case MACCESS_PWIDTH_8: - src = mystique->dwgreg.fcol; + src = mystique->dwgreg.pattern[pattern_y][pattern_x] ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); @@ -4402,7 +4406,7 @@ blit_line(mystique_t *mystique, int closed, int autoline) break; case MACCESS_PWIDTH_16: - src = mystique->dwgreg.fcol; + src = mystique->dwgreg.pattern[pattern_y][pattern_x] ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; dst = ((uint16_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); @@ -4419,7 +4423,7 @@ blit_line(mystique_t *mystique, int closed, int autoline) break; case MACCESS_PWIDTH_24: - src = mystique->dwgreg.fcol; + src = mystique->dwgreg.pattern[pattern_y][pattern_x] ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; old_dst = *(uint32_t *) &svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); @@ -4436,7 +4440,7 @@ blit_line(mystique_t *mystique, int closed, int autoline) break; case MACCESS_PWIDTH_32: - src = mystique->dwgreg.fcol; + src = mystique->dwgreg.pattern[pattern_y][pattern_x] ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; dst = ((uint32_t *) svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); @@ -4479,6 +4483,7 @@ blit_line(mystique_t *mystique, int closed, int autoline) mystique->dwgreg.err += mystique->dwgreg.k1; mystique->dwgreg.length--; + mystique->dwgreg.funcnt--; } break; @@ -5106,8 +5111,8 @@ texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atra s = (int32_t) mystique->dwgreg.tmr[6] >> s_shift; t = (int32_t) mystique->dwgreg.tmr[7] >> t_shift; - s_frac = (((int32_t) mystique->dwgreg.tmr[6] >> s_shift) & ((1 << s_shift) - 1)) / (double)(1 << s_shift); - t_frac = (((int32_t) mystique->dwgreg.tmr[7] >> t_shift) & ((1 << t_shift) - 1)) / (double)(1 << t_shift); + s_frac = (((int32_t) mystique->dwgreg.tmr[6]) & ((1 << s_shift) - 1)) / (double)(1 << s_shift); + t_frac = (((int32_t) mystique->dwgreg.tmr[7]) & ((1 << t_shift) - 1)) / (double)(1 << t_shift); } else { const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); @@ -5116,7 +5121,7 @@ texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atra s = ((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q) >> s_shift; t = ((int64_t) (int32_t) mystique->dwgreg.tmr[7] * q) >> t_shift; s_frac = (((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q) & ((1 << s_shift) - 1)) / (double)(1 << s_shift); - t_frac = (((int64_t) (int32_t) mystique->dwgreg.tmr[6] * q) & ((1 << t_shift) - 1)) / (double)(1 << t_shift); + t_frac = (((int64_t) (int32_t) mystique->dwgreg.tmr[7] * q) & ((1 << t_shift) - 1)) / (double)(1 << t_shift); } if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { @@ -5328,6 +5333,15 @@ blit_texture_trap(mystique_t *mystique) } break; + case (TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY): + if (!ctransp) + goto skip_pixel; + + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + break; + default: fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); } @@ -6807,11 +6821,13 @@ millennium_ii_available(void) return rom_present(ROM_MILLENNIUM_II); } +#ifdef USE_G100 static int matrox_g100_available(void) { return rom_present(ROM_G100); } +#endif static void mystique_speed_changed(void *priv) @@ -6949,6 +6965,7 @@ const device_t millennium_ii_device = { .config = millennium_ii_config }; +#ifdef USE_G100 const device_t productiva_g100_device = { .name = "Matrox Productiva G100", .internal_name = "productiva_g100", @@ -6962,3 +6979,4 @@ const device_t productiva_g100_device = { .force_redraw = mystique_force_redraw, .config = millennium_ii_config }; +#endif diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index f5bc449e69..f21e9d66c0 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -36,13 +36,16 @@ #define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM" #define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM" #define BIOS_077_PATH "roms/video/oti/oti077.vbi" +#define BIOS_077_ACER100T_PATH "roms/machines/acer100t/oti077_acer100t.BIN" + enum { OTI_037C = 0, OTI_067 = 2, OTI_067_AMA932J = 3, OTI_067_M300 = 4, - OTI_077 = 5 + OTI_077 = 5, + OTI_077_ACER100T = 6 }; typedef struct { @@ -92,7 +95,7 @@ oti_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077) + if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); else svga_out(addr, val, svga); @@ -153,7 +156,7 @@ oti_out(uint16_t addr, uint8_t val, void *priv) mem_mapping_disable(&svga->mapping); else mem_mapping_enable(&svga->mapping); - } else if (oti->chip_id == OTI_077) { + } else if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) { svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; switch ((val & 0xc0) >> 6) { @@ -238,7 +241,7 @@ oti_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077) + if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); return svga_in(addr, svga); @@ -464,6 +467,12 @@ oti_init(const device_t *info) oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); break; + case OTI_077_ACER100T: + romfn = BIOS_077_ACER100T_PATH; + oti->vram_size = device_get_config_int("memory"); + oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ + io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); + break; default: break; @@ -476,12 +485,19 @@ oti_init(const device_t *info) oti->vram_mask = (oti->vram_size << 10) - 1; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); + if (oti->chip_id == OTI_077_ACER100T){ + /* josephillips: Required to show all BIOS + information on Acer 100T only + */ + video_inform(0x1,&timing_oti); + }else{ + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); + } svga_init(info, &oti->svga, oti, oti->vram_size << 10, oti_recalctimings, oti_in, oti_out, NULL, NULL); - if (oti->chip_id == OTI_077) + if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ io_sethandler(0x03c0, 32, @@ -489,7 +505,7 @@ oti_init(const device_t *info) oti->svga.miscout = 1; oti->svga.packed_chain4 = 1; - + return oti; } @@ -531,6 +547,12 @@ oti067_ama932j_available(void) return (rom_present(BIOS_067_AMA932J_PATH)); } +static int +oti077_acer100t_available(void) +{ + return (rom_present(BIOS_077_ACER100T_PATH)); +} + static int oti067_077_available(void) { @@ -597,6 +619,35 @@ static const device_config_t oti067_ama932j_config[] = { } }; +static const device_config_t oti077_acer100t_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; + static const device_config_t oti077_config[] = { { .name = "memory", @@ -683,6 +734,21 @@ const device_t oti067_ama932j_device = { .config = oti067_ama932j_config }; +const device_t oti077_acer100t_device = { + .name = "Oak OTI-077 (Acer 100T)", + .internal_name = "oti077_acer100t", + .flags = DEVICE_ISA, + .local = 6, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti077_acer100t_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti077_acer100t_config +}; + + const device_t oti077_device = { .name = "Oak OTI-077", .internal_name = "oti077", diff --git a/src/video/vid_ogc.c b/src/video/vid_ogc.c index c3073898df..9ac94169c3 100644 --- a/src/video/vid_ogc.c +++ b/src/video/vid_ogc.c @@ -97,11 +97,14 @@ ogc_out(uint16_t addr, uint8_t val, void *priv) cga_out(addr, val, &ogc->cga); break; + case 0x3db: case 0x3de: - /* set control register */ - ogc->ctrl_3de = val; - /* select 1st or 2nd 16k vram block to be used */ - ogc->base = (val & 0x08) ? 0x4000 : 0; + if (addr == ogc->ctrl_addr) { + /* set control register */ + ogc->ctrl_3de = val; + /* select 1st or 2nd 16k vram block to be used */ + ogc->base = (val & 0x08) ? 0x4000 : 0; + } break; default: @@ -622,6 +625,8 @@ ogc_init(UNUSED(const device_t *info)) else ogc->mono_display = 1; + ogc->ctrl_addr = 0x3de; + return ogc; } diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 30666e82cc..73902345de 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -38,8 +38,6 @@ typedef struct paradise_t { rom_t bios_rom; - uint8_t bank_mask; - enum { PVGA1A = 0, WD90C11, @@ -47,11 +45,11 @@ typedef struct paradise_t { } type; uint32_t vram_mask; + uint32_t memory; uint32_t read_bank[4], write_bank[4]; int interlace; - int check; struct { uint8_t reg_block_ptr; @@ -79,7 +77,6 @@ paradise_in(uint16_t addr, void *priv) { paradise_t *paradise = (paradise_t *) priv; svga_t *svga = ¶dise->svga; - uint8_t temp = 0; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -109,16 +106,6 @@ paradise_in(uint16_t addr, void *priv) return 0xff; } switch (svga->gdcaddr) { - case 0x0b: - temp = svga->gdcreg[0x0b]; - if (paradise->type == WD90C30) { - if (paradise->vram_mask == ((512 << 10) - 1)) { - temp &= ~0x40; - temp |= 0xc0; - } - } - return temp; - case 0x0f: return (svga->gdcreg[0x0f] & 0x17) | 0x80; @@ -149,11 +136,6 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) svga_t *svga = ¶dise->svga; uint8_t old; - if (paradise->vram_mask <= ((512 << 10) - 1)) - paradise->bank_mask = 0x7f; - else - paradise->bank_mask = 0xff; - if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -186,24 +168,23 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) return; } - old = svga->gdcreg[svga->gdcaddr]; switch (svga->gdcaddr) { case 6: - if (old ^ (val & 0x0c)) { + if ((svga->gdcreg[6] & 0x0c) != (val & 0xc)) { switch (val & 0x0c) { - case 0x00: /*128k at A0000*/ + case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; - case 0x04: /*64k at A0000*/ + case 0x4: /*64k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; break; - case 0x08: /*32k at B0000*/ + case 0x8: /*32k at B0000*/ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); svga->banked_mask = 0x7fff; break; - case 0x0c: /*32k at B8000*/ + case 0xC: /*32k at B8000*/ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; @@ -211,18 +192,26 @@ paradise_out(uint16_t addr, uint8_t val, void *priv) default: break; } - svga->gdcreg[6] = val; - paradise_remap(paradise); } + svga->gdcreg[6] = val; + paradise_remap(paradise); return; case 9: case 0x0a: - svga->gdcreg[svga->gdcaddr] = val & paradise->bank_mask; + svga->gdcreg[svga->gdcaddr] = val; paradise_remap(paradise); return; case 0x0b: svga->gdcreg[0x0b] = val; + svga->gdcreg[0x0b] &= ~0xc0; + if (paradise->memory == 1024) + svga->gdcreg[0x0b] |= 0xc0; + else if (paradise->memory == 512) + svga->gdcreg[0x0b] |= 0x80; + else + svga->gdcreg[0x0b] |= 0x40; + paradise_remap(paradise); return; case 0x0e: @@ -277,8 +266,6 @@ paradise_remap(paradise_t *paradise) { svga_t *svga = ¶dise->svga; - paradise->check = 0; - if (svga->seqregs[0x11] & 0x80) { paradise->read_bank[0] = paradise->read_bank[2] = svga->gdcreg[9] << 12; paradise->read_bank[1] = paradise->read_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); @@ -303,12 +290,13 @@ paradise_remap(paradise_t *paradise) paradise->write_bank[1] = paradise->write_bank[3] = (svga->gdcreg[9] << 12) + ((svga->gdcreg[6] & 0x08) ? 0 : 0x8000); } - if (((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4 && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[6] >> 2) & 3) == 1) - paradise->check = 1; - - if (paradise->bank_mask == 0x7f) { + /*There are separate drivers for 1M and 512K/256K versions of the PVGA chips.*/ + if ((svga->gdcreg[0x0b] & 0xc0) < 0xc0) { paradise->read_bank[1] &= 0x7ffff; paradise->write_bank[1] &= 0x7ffff; + } else { + paradise->read_bank[1] &= 0xfffff; + paradise->write_bank[1] &= 0xfffff; } } @@ -317,6 +305,8 @@ paradise_recalctimings(svga_t *svga) { const paradise_t *paradise = (paradise_t *) svga->priv; + svga->lowres = !(svga->gdcreg[0x0e] & 0x01); + if (paradise->type == WD90C30) { if (svga->crtc[0x3e] & 0x01) svga->vtotal |= 0x400; @@ -330,22 +320,18 @@ paradise_recalctimings(svga_t *svga) svga->split |= 0x400; svga->interlace = !!(svga->crtc[0x2d] & 0x20); - - if (!svga->interlace && !(svga->gdcreg[0x0e] & 0x01) && (svga->hdisp >= 1024) && ((svga->gdcreg[5] & 0x60) == 0) && (svga->miscout >= 0x27) && (svga->miscout <= 0x2f) && ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1))) { /*Horrible tweak to re-enable the interlace after returning to - a windowed DOS box in Win3.x*/ - svga->interlace = 1; - } } if (paradise->type < WD90C30) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { + if ((svga->bpp >= 8) && !svga->lowres) { svga->render = svga_render_8bpp_highres; + svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; } } } else { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { - if ((svga->bpp >= 8) && (svga->gdcreg[0x0e] & 0x01)) { + if ((svga->bpp >= 8) && !svga->lowres) { if (svga->bpp == 16) { svga->render = svga_render_16bpp_highres; svga->hdisp >>= 1; @@ -360,13 +346,16 @@ paradise_recalctimings(svga_t *svga) svga->hdisp += 12; if (svga->hdisp == 800) svga->ma_latch -= 3; - } else { + } else svga->render = svga_render_8bpp_highres; - } - } + + svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; + } else if ((svga->bpp <= 8) && svga->lowres && !svga->interlace && (svga->hdisp >= 1024) && + (svga->miscout >= 0x27) && (svga->miscout <= 0x2f)) + svga->interlace = 1; /*Horrible tweak to re-enable the interlace after returning to + a windowed DOS box in Win3.x*/ } } - svga->vram_display_mask = (svga->crtc[0x2f] & 0x02) ? 0x3ffff : paradise->vram_mask; } static void @@ -377,51 +366,31 @@ paradise_write(uint32_t addr, uint8_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->gdcreg[5] & 0x40)) { - svga_write(addr, val, svga); - return; - } - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (svga->gdcreg[0x0e] & 0x01) { - if (paradise->check) { + if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { + if (((svga->gdcreg[6] & 0x0c) == 0x04) && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) + if (prev_addr == 3) { + if ((addr & 0x30000) != 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) + } else if (prev_addr == 2) { + if ((addr & 0x30000) != 0x20000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) + } else if (prev_addr == 1) { + if ((addr & 0x30000) != 0x10000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) + } else { + if (addr & 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; } } } svga_write_linear(addr, val, svga); } + static void paradise_writew(uint32_t addr, uint16_t val, void *priv) { @@ -430,45 +399,24 @@ paradise_writew(uint32_t addr, uint16_t val, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->gdcreg[5] & 0x40)) { - svga_writew(addr, val, svga); - return; - } - addr = (addr & 0x7fff) + paradise->write_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (svga->gdcreg[0x0e] & 0x01) { - if (paradise->check) { + if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { + if (((svga->gdcreg[6] & 0x0c) == 0x04) && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) + if (prev_addr == 3) { + if ((addr & 0x30000) != 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) + } else if (prev_addr == 2) { + if ((addr & 0x30000) != 0x20000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) + } else if (prev_addr == 1) { + if ((addr & 0x30000) != 0x10000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) + } else { + if (addr & 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; } } @@ -484,50 +432,31 @@ paradise_read(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->gdcreg[5] & 0x40)) { - return svga_read(addr, svga); - } - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (svga->gdcreg[0x0e] & 0x01) { - if (paradise->check) { + if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { + if (((svga->gdcreg[6] & 0x0c) == 0x04) && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) + if (prev_addr == 3) { + if ((addr & 0x30000) != 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) + } else if (prev_addr == 2) { + if ((addr & 0x30000) != 0x20000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) + } else if (prev_addr == 1) { + if ((addr & 0x30000) != 0x10000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) + } else { + if (addr & 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; } } } return svga_read_linear(addr, svga); } + static uint16_t paradise_readw(uint32_t addr, void *priv) { @@ -536,44 +465,24 @@ paradise_readw(uint32_t addr, void *priv) uint32_t prev_addr; uint32_t prev_addr2; - if (!(svga->gdcreg[5] & 0x40)) { - return svga_readw(addr, svga); - } - addr = (addr & 0x7fff) + paradise->read_bank[(addr >> 15) & 3]; /*Could be done in a better way but it works.*/ - if (svga->gdcreg[0x0e] & 0x01) { - if (paradise->check) { + if (!svga->lowres || (svga->attrregs[0x10] & 0x40)) { + if (((svga->gdcreg[6] & 0x0c) == 0x04) && (svga->crtc[0x14] & 0x40) && ((svga->gdcreg[0x0b] & 0xc0) == 0xc0) && !svga->chain4) { prev_addr = addr & 3; prev_addr2 = addr & 0xfffc; - if ((addr & 3) == 3) { - if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 2) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 1) { - if ((addr & 0x30000) == 0x30000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) + if (prev_addr == 3) { + if ((addr & 0x30000) != 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x00000) + } else if (prev_addr == 2) { + if ((addr & 0x30000) != 0x20000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - } else if ((addr & 3) == 0) { - if ((addr & 0x30000) == 0x30000) + } else if (prev_addr == 1) { + if ((addr & 0x30000) != 0x10000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x20000) - addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; - else if ((addr & 0x30000) == 0x10000) + } else { + if (addr & 0x30000) addr = (addr >> 16) | (prev_addr << 16) | prev_addr2; } } @@ -582,7 +491,7 @@ paradise_readw(uint32_t addr, void *priv) } void * -paradise_init(const device_t *info, uint32_t memsize) +paradise_init(const device_t *info, uint32_t memory) { paradise_t *paradise = malloc(sizeof(paradise_t)); svga_t *svga = ¶dise->svga; @@ -593,33 +502,35 @@ paradise_init(const device_t *info, uint32_t memsize) else video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_paradise_wd90c); + paradise->memory = memory; + switch (info->local) { case PVGA1A: - svga_init(info, svga, paradise, memsize, /*256kb*/ + svga_init(info, svga, paradise, (memory << 10), /*256kb default*/ paradise_recalctimings, paradise_in, paradise_out, NULL, NULL); - paradise->vram_mask = memsize - 1; - svga->decode_mask = memsize - 1; + paradise->vram_mask = (memory << 10) - 1; + svga->decode_mask = (memory << 10) - 1; break; case WD90C11: - svga_init(info, svga, paradise, 1 << 19, /*512kb*/ + svga_init(info, svga, paradise, (memory << 10), /*512kb default*/ paradise_recalctimings, paradise_in, paradise_out, NULL, NULL); - paradise->vram_mask = (1 << 19) - 1; - svga->decode_mask = (1 << 19) - 1; + paradise->vram_mask = (memory << 10) - 1; + svga->decode_mask = (memory << 10) - 1; break; case WD90C30: - svga_init(info, svga, paradise, memsize, + svga_init(info, svga, paradise, (memory << 10), paradise_recalctimings, paradise_in, paradise_out, NULL, NULL); - paradise->vram_mask = memsize - 1; - svga->decode_mask = memsize - 1; + paradise->vram_mask = (memory << 10) - 1; + svga->decode_mask = (memory << 10) - 1; svga->ramdac = device_add(&sc11487_ramdac_device); /*Actually a Winbond W82c487-80, probably a clone.*/ break; @@ -664,7 +575,7 @@ paradise_init(const device_t *info, uint32_t memsize) static void * paradise_pvga1a_ncr3302_init(const device_t *info) { - paradise_t *paradise = paradise_init(info, 1 << 18); + paradise_t *paradise = paradise_init(info, 256); if (paradise) rom_init(¶dise->bios_rom, "roms/machines/3302/c000-wd_1987-1989-740011-003058-019c.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -675,7 +586,7 @@ paradise_pvga1a_ncr3302_init(const device_t *info) static void * paradise_pvga1a_pc2086_init(const device_t *info) { - paradise_t *paradise = paradise_init(info, 1 << 18); + paradise_t *paradise = paradise_init(info, 256); if (paradise) rom_init(¶dise->bios_rom, "roms/machines/pc2086/40186.ic171", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -686,7 +597,7 @@ paradise_pvga1a_pc2086_init(const device_t *info) static void * paradise_pvga1a_pc3086_init(const device_t *info) { - paradise_t *paradise = paradise_init(info, 1 << 18); + paradise_t *paradise = paradise_init(info, 256); if (paradise) rom_init(¶dise->bios_rom, "roms/machines/pc3086/c000.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -698,12 +609,9 @@ static void * paradise_pvga1a_standalone_init(const device_t *info) { paradise_t *paradise; - uint32_t memory = 512; + uint32_t memsize = device_get_config_int("memory"); - memory = device_get_config_int("memory"); - memory <<= 10; - - paradise = paradise_init(info, memory); + paradise = paradise_init(info, memsize); if (paradise) rom_init(¶dise->bios_rom, "roms/video/pvga1a/BIOS.BIN", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -720,7 +628,7 @@ paradise_pvga1a_standalone_available(void) static void * paradise_wd90c11_megapc_init(const device_t *info) { - paradise_t *paradise = paradise_init(info, 0); + paradise_t *paradise = paradise_init(info, 512); if (paradise) rom_init_interleaved(¶dise->bios_rom, @@ -734,7 +642,7 @@ paradise_wd90c11_megapc_init(const device_t *info) static void * paradise_wd90c11_standalone_init(const device_t *info) { - paradise_t *paradise = paradise_init(info, 0); + paradise_t *paradise = paradise_init(info, 512); if (paradise) rom_init(¶dise->bios_rom, "roms/video/wd90c11/WD90C11.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -752,12 +660,9 @@ static void * paradise_wd90c30_standalone_init(const device_t *info) { paradise_t *paradise; - uint32_t memory = 512; - - memory = device_get_config_int("memory"); - memory <<= 10; + uint32_t memsize = device_get_config_int("memory"); - paradise = paradise_init(info, memory); + paradise = paradise_init(info, memsize); if (paradise) rom_init(¶dise->bios_rom, "roms/video/wd90c30/90C30-LR.VBI", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); @@ -916,6 +821,10 @@ static const device_config_t paradise_wd90c30_config[] = { .type = CONFIG_SELECTION, .default_int = 1024, .selection = { + { + .description = "256 kB", + .value = 256 + }, { .description = "512 kB", .value = 512 diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 8fa86dfe00..2b14284c7a 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -75,6 +75,7 @@ #define ROM_SPEA_MERCURY_P64V "roms/video/s3/S3_968PCI_TVP3026_SPEAMecuryP64V_ver1.01.BIN" #define ROM_NUMBER9_9FX_771 "roms/video/s3/no9motionfx771.BIN" #define ROM_PHOENIX_VISION968 "roms/video/s3/1-DSV3968P.BIN" +#define ROM_DIAMOND_STEALTH64_968 "roms/video/s3/vv_303.rom" enum { S3_NUMBER9_9FX, @@ -115,7 +116,8 @@ enum { S3_NUMBER9_9FX_531, S3_NUMBER9_9FX_771, S3_SPEA_MERCURY_LITE_PCI, - S3_86C805_ONBOARD + S3_86C805_ONBOARD, + S3_DIAMOND_STEALTH64_968 }; enum { @@ -143,7 +145,6 @@ static video_timings_t timing_s3_stealth64_vlb = { .type = VIDEO_BUS, .write_b = static video_timings_t timing_s3_stealth64_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; static video_timings_t timing_s3_vision864_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; static video_timings_t timing_s3_vision864_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; -static video_timings_t timing_s3_vision868_vlb = { .type = VIDEO_BUS, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; static video_timings_t timing_s3_vision868_pci = { .type = VIDEO_PCI, .write_b = 4, .write_w = 4, .write_l = 5, .read_b = 20, .read_w = 20, .read_l = 35 }; static video_timings_t timing_s3_vision964_vlb = { .type = VIDEO_BUS, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; static video_timings_t timing_s3_vision964_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 20, .read_w = 20, .read_l = 35 }; @@ -364,7 +365,7 @@ typedef struct s3_t { event_t *wake_fifo_thread; event_t *fifo_not_full_event; - int blitter_busy; + atomic_int blitter_busy; uint64_t blitter_time; uint64_t status_time; @@ -386,6 +387,8 @@ typedef struct s3_t { void (*accel_start)(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, void *priv); } s3_t; +static s3_t *reset_state = NULL; + #define INT_VSY (1 << 0) #define INT_GE_BSY (1 << 1) #define INT_FIFO_OVR (1 << 2) @@ -947,6 +950,10 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x9ae9: s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8); s3->accel.ssv_state = 0; + if (s3->bpp == 3) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] &= ~0x10; + } s3->accel_start(-1, 0, 0xffffffff, 0, s3); break; @@ -982,20 +989,50 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0xa148: case 0xa2e8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } + } else s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; break; case 0xa149: case 0xa2e9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } if (s3->accel.color_16bit_check) s3->accel.bkgd_color_actual[1] = s3->accel.bkgd_color & 0xff; else @@ -1003,43 +1040,79 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa14a: case 0xa2ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val; + } } break; case 0xa14b: case 0xa2eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); - else - s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24); + else + s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xa548: case 0xa6e8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } + } else s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; break; case 0xa549: case 0xa6e9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } if (s3->accel.color_16bit_check) s3->accel.frgd_color_actual[1] = s3->accel.frgd_color & 0xff; @@ -1048,43 +1121,79 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa54a: case 0xa6ea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if ((s3->accel.multifunc[0xe] & 0x10)) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val; + } } break; case 0xa54b: case 0xa6eb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); - else - s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24); + else + s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xa948: case 0xaae8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } + } else s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; break; case 0xa949: case 0xaae9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } if (s3->accel.color_16bit_check) s3->accel.wrt_mask_actual[1] = s3->accel.wrt_mask & 0xff; @@ -1093,83 +1202,296 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; case 0xa94a: case 0xaaea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val; + } } break; case 0xa94b: case 0xaaeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); - else - s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24); + else + s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xad48: case 0xaee8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } + } else s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; break; case 0xad49: case 0xaee9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } break; case 0xad4a: case 0xaeea: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val; + } } break; case 0xad4b: case 0xaeeb: - if (s3->accel.multifunc[0xe] & 0x200) - s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else if (s3->bpp == 3) { - if (s3->accel.multifunc[0xe] & 0x10) + if (s3->chip >= S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x200) s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); - else - s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); - s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24); + else + s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } } break; case 0xb148: case 0xb2e8: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } + } else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val; + } else { + s3->accel.b2e8_pix = 1; + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[0] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3->accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + else + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } else { + if (s3->accel.color_16bit_check_rectfill) { + if (s3->accel.color_16bit_check) { + if (s3->accel.pix_trans_x_count < s3->accel.pix_trans_ptr_cnt) { + s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, " + "check=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count] = val; + s3->accel.pix_trans_x_count++; + s3->accel.pix_trans_x_count2 = s3->accel.pix_trans_x_count; + } + } else { + if (s3->accel.pix_trans_x_count2 < s3->accel.pix_trans_ptr_cnt) { + s3_log("Byte: CPU data CMD=%04x, byte write=%02x, cnt=%d, " + "check=%d.\n", s3->accel.cmd, val, + s3->accel.pix_trans_x_count2, s3->accel.color_16bit_check); + s3->accel.pix_trans_ptr[s3->accel.pix_trans_x_count2] = val; + s3->accel.pix_trans_x_count2++; + } + s3_log("WriteCNT=%d, TotalCNT=%d.\n", s3->accel.pix_trans_x_count2, + s3->accel.pix_trans_ptr_cnt); + if (s3->accel.pix_trans_x_count2 == s3->accel.pix_trans_ptr_cnt) { + for (int i = 0; i < s3->accel.pix_trans_ptr_cnt; i += 2) { + s3_log("Transferring write count=%d, bytes=%04x.\n", i, + s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8)); + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans_ptr[i] | + (s3->accel.pix_trans_ptr[i + 1] << 8), s3); + } + + s3->accel.pix_trans_x_count2 = 0; + s3->accel.color_16bit_check_rectfill = 0; + if (s3->accel.pix_trans_ptr != NULL) { + free(s3->accel.pix_trans_ptr); + s3->accel.pix_trans_ptr = NULL; + } + } + } + break; + } + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3); + } + break; + + default: + break; + } + } + } break; case 0xb149: case 0xb2e9: - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); - else - s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + if (s3->bpp == 3) { + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) { + if (s3->accel.multifunc[0xe] & 0x10) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + + s3->accel.multifunc[0xe] ^= 0x10; + } else if (s3->chip >= S3_VISION964) { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); + else + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { + s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + + if ((s3->chip >= S3_86C928) && (s3->chip < S3_VISION964)) + s3->accel.multifunc[0xe] ^= 0x10; + else if (s3->chip >= S3_VISION964) { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } + } else { + s3->accel.b2e8_pix = 1; + if (s3_cpu_dest(s3)) + break; + s3->accel.pix_trans[1] = val; + if (s3->accel.cmd & 0x100) { + switch (s3->accel.cmd & 0x600) { + case 0x000: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || + ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3->accel_start(8, 1, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + } else + s3->accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + break; + case 0x200: + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || + ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3->accel_start(16, 1, s3->accel.pix_trans[1] | + (s3->accel.pix_trans[0] << 8), 0, s3); + else + s3->accel_start(16, 1, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | + (s3->accel.pix_trans[0] << 8), s3); + else + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | + (s3->accel.pix_trans[0] << 8), s3); + else + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | + (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x400: + if (svga->crtc[0x53] & 0x08) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) + s3->accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3); + else + s3->accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } else + s3->accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3); + } + break; + case 0x600: + if (s3->chip == S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868 || s3->chip >= S3_TRIO64V) { + if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + s3->accel_start(8, 1, s3->accel.pix_trans[1], 0, s3); + s3->accel_start(8, 1, s3->accel.pix_trans[0], 0, s3); + } + } + } + break; + + default: + break; + } + + } + } break; case 0xb14a: case 0xb2ea: @@ -1191,6 +1513,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24); else s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8); + s3->accel.multifunc[0xe] ^= 0x10; } break; @@ -1388,9 +1711,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) break; s3->accel.pix_trans[1] = val; if (s3->accel.cmd & 0x100) { - s3_log("S3 PIXTRANS_B write (E2E9): cmd=%03x, pixelcntl=%02x, frgdmix=%02x, " - "bkgdmix=%02x, curx=%d, val=%04x.\n", s3->accel.cmd, s3->accel.multifunc[0x0a], - s3->accel.frgd_mix, s3->accel.bkgd_mix, s3->accel.cur_x, val); switch (s3->accel.cmd & 0x600) { case 0x000: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { @@ -1538,13 +1858,26 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) { - if (port != 0x9ee8 && port != 0x9d48) { - if (port == 0xb2e8 || port == 0xb148) { - s3->accel.b2e8_pix = 1; + if ((port != 0x9ee8) && (port != 0x9d48)) { + if ((port == 0xb2e8) || (port == 0xb148)) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + } else { + s3->accel.b2e8_pix = 1; + s3_accel_out_pixtrans_w(s3, val); + } } else { + s3_log("Port WriteW FIFO=%04x, val=%04x, bussize=%03x.\n", port, val, s3->accel.cmd & 0x600); s3->accel.b2e8_pix = 0; + if ((port == 0xe2e8) || (port == 0xe2ea) || (port == 0xe148) || (port == 0xe14a)) + s3_accel_out_pixtrans_w(s3, val); + else { + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + } } - s3_accel_out_pixtrans_w(s3, val); } else { s3->accel.short_stroke = val; s3->accel.ssv_state = 1; @@ -1565,12 +1898,29 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val) { - if (port == 0xb2e8 || port == 0xb148) - s3->accel.b2e8_pix = 1; - else + if ((port == 0xb2e8) || (port == 0xb148)) { + if ((s3->accel.multifunc[0xe] & 0x100) || (s3->chip >= S3_86C928)) { + s3->accel.b2e8_pix = 0; + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + s3_accel_out_fifo(s3, port + 2, val >> 16); + s3_accel_out_fifo(s3, port + 3, val >> 24); + } else { + s3->accel.b2e8_pix = 1; + s3_accel_out_pixtrans_l(s3, val); + } + } else { s3->accel.b2e8_pix = 0; - - s3_accel_out_pixtrans_l(s3, val); + s3_log("Port WriteL FIFO=%04x, val=%08x, bussize=%03x.\n", port, val, s3->accel.cmd & 0x600); + if ((port == 0xe2e8) || (port == 0xe148)) + s3_accel_out_pixtrans_l(s3, val); + else { + s3_accel_out_fifo(s3, port, val); + s3_accel_out_fifo(s3, port + 1, val >> 8); + s3_accel_out_fifo(s3, port + 2, val >> 16); + s3_accel_out_fifo(s3, port + 3, val >> 24); + } + } } static void @@ -1746,77 +2096,7 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) s3->accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3); } } else { - switch (addr & 0x1ffff) { - case 0x83b0: - case 0x83b1: - case 0x83b2: - case 0x83b3: - case 0x83b4: - case 0x83b5: - case 0x83b6: - case 0x83b7: - case 0x83b8: - case 0x83b9: - case 0x83ba: - case 0x83bb: - case 0x83bc: - case 0x83bd: - case 0x83be: - case 0x83bf: - case 0x83c0: - case 0x83c1: - case 0x83c2: - case 0x83c3: - case 0x83c4: - case 0x83c5: - case 0x83c6: - case 0x83c7: - case 0x83c8: - case 0x83c9: - case 0x83ca: - case 0x83cb: - case 0x83cc: - case 0x83cd: - case 0x83ce: - case 0x83cf: - case 0x83d0: - case 0x83d1: - case 0x83d2: - case 0x83d3: - case 0x83d4: - case 0x83d5: - case 0x83d6: - case 0x83d7: - case 0x83d8: - case 0x83d9: - case 0x83da: - case 0x83db: - case 0x83dc: - case 0x83dd: - case 0x83de: - case 0x83df: - s3_out(addr & 0x3ff, val, s3); - break; - case 0x8504: - s3->subsys_stat &= ~val; - s3_update_irqs(s3); - break; - case 0x8505: - s3->subsys_cntl = val; - s3_update_irqs(s3); - break; - case 0x850c: - s3->accel.advfunc_cntl = val; - s3_updatemapping(s3); - break; - case 0xff20: - s3->serialport = val; - i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); - break; - default: - s3_accel_out_fifo(s3, addr & 0xffff, val); - break; - } + s3_accel_out_fifo(s3, addr & 0xffff, val); } } else { if (addr & 0x8000) { @@ -1855,45 +2135,21 @@ s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val) static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) { - const svga_t *svga = &s3->svga; - - if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1fffe) < 0x8000) { - s3_accel_out_pixtrans_w(s3, val); - } else { - switch (addr & 0x1fffe) { - default: - case 0x83d4: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - break; - case 0xff20: - s3_accel_write_fifo(s3, addr, val); - break; - case 0x811c: - s3_accel_out_fifo_w(s3, 0x9ee8, val); - break; - } - } - } else { - if (addr & 0x8000) { - if (addr == 0x811c) - s3_accel_out_fifo_w(s3, 0x9ee8, val); + if ((addr & 0x1fffe) < 0x8000) { + s3_accel_out_pixtrans_w(s3, val); + } else if ((addr & 0x1fffe) == 0x811c) { + s3_accel_out_fifo_w(s3, 0x9ee8, val); + } else if (((addr & 0x1fffe) >= 0x8000) && (addr & 0x1fffe) < 0x10000) { + if (((addr & 0x1fffe) == 0xe2e8) || ((addr & 0x1fffe) == 0xe2ea)) { + if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) + s3_accel_out_pixtrans_w(s3, val); else { - if ((addr == 0xe2e8) || (addr == 0xe2ea)) { - if ((s3->chip == S3_86C801) || (s3->chip == S3_86C805) || (s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) - s3_accel_out_pixtrans_w(s3, val); - else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } - } else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - } + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); } } else { - s3_accel_out_pixtrans_w(s3, val); + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); } } } @@ -1901,221 +2157,78 @@ s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val) static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val) { - svga_t *svga = &s3->svga; - - if (svga->crtc[0x53] & 0x08) { - if ((addr & 0x1fffc) < 0x8000 || ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000)) { - if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { - s3_visionx68_video_engine_op(val, s3); - } else if ((addr & 0x1fffc) < 0x8000) { - s3_accel_out_pixtrans_l(s3, val); - } - } else { - switch (addr & 0x1fffc) { - case 0x8180: - s3->streams.pri_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x8184: - s3->streams.chroma_ctrl = val; - break; - case 0x8190: - s3->streams.sec_ctrl = val; - s3->streams.dda_horiz_accumulator = val & 0xfff; - if (val & (1 << 11)) - s3->streams.dda_horiz_accumulator |= 0xfffff800; - s3->streams.sdif = (val >> 24) & 7; - break; - case 0x8194: - s3->streams.chroma_upper_bound = val; - break; - case 0x8198: - s3->streams.sec_filter = val; - s3->streams.k1_horiz_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k1_horiz_scale |= 0xfffff800; - s3->streams.k2_horiz_scale = (val >> 16) & 0x7ff; - if ((val >> 16) & (1 << 10)) - s3->streams.k2_horiz_scale |= 0xfffff800; - break; - case 0x81a0: - s3->streams.blend_ctrl = val; - break; - case 0x81c0: - s3->streams.pri_fb0 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81c4: - s3->streams.pri_fb1 = val & 0x3fffff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81c8: - s3->streams.pri_stride = val & 0xfff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81cc: - s3->streams.buffer_ctrl = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81d0: - s3->streams.sec_fb0 = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81d4: - s3->streams.sec_fb1 = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81d8: - s3->streams.sec_stride = val; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81dc: - s3->streams.overlay_ctrl = val; - break; - case 0x81e0: - s3->streams.k1_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k1_vert_scale |= 0xfffff800; - break; - case 0x81e4: - s3->streams.k2_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - s3->streams.k2_vert_scale |= 0xfffff800; - break; - case 0x81e8: - s3->streams.dda_vert_accumulator = val & 0xfff; - if (val & (1 << 11)) - s3->streams.dda_vert_accumulator |= 0xfffff800; - break; - case 0x81ec: - s3->streams.fifo_ctrl = val; - break; - case 0x81f0: - s3->streams.pri_start = val; - s3->streams.pri_x = (val >> 16) & 0x7ff; - s3->streams.pri_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81f4: - s3->streams.pri_size = val; - s3->streams.pri_w = (val >> 16) & 0x7ff; - s3->streams.pri_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81f8: - s3->streams.sec_start = val; - s3->streams.sec_x = (val >> 16) & 0x7ff; - s3->streams.sec_y = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - case 0x81fc: - s3->streams.sec_size = val; - s3->streams.sec_w = (val >> 16) & 0x7ff; - s3->streams.sec_h = val & 0x7ff; - svga_recalctimings(svga); - svga->fullchange = svga->monitor->mon_changeframecount; - break; - - case 0x8504: - s3->subsys_stat &= ~(val & 0xff); - s3->subsys_cntl = (val >> 8); - s3_update_irqs(s3); - break; - - case 0x850c: - s3->accel.advfunc_cntl = val & 0xff; - s3_updatemapping(s3); - break; - - case 0xff20: - s3_accel_write_fifo(s3, addr, val); - break; - - case 0x18080: - s3->videoengine.nop = 1; - break; + if ((addr & 0x1fffc) >= 0x10000 && (addr & 0x1fffc) < 0x18000) { + s3_visionx68_video_engine_op(val, s3); + } else if ((addr & 0x1fffc) < 0x8000) { + s3_accel_out_pixtrans_l(s3, val); + } else if ((addr & 0x1fffc) >= 0x18000) { + switch (addr & 0x1fffc) { + case 0x18080: + s3->videoengine.nop = 1; + break; - case 0x18088: - s3->videoengine.cntl = val; - s3->videoengine.dda_init_accumulator = val & 0xfff; - s3->videoengine.odf = (val >> 16) & 7; - s3->videoengine.yuv = !!(val & (1 << 19)); - s3->videoengine.idf = (val >> 20) & 7; - s3->videoengine.dither = !!(val & (1 << 29)); - s3->videoengine.dm_index = (val >> 23) & 7; - break; + case 0x18088: + s3->videoengine.cntl = val; + s3->videoengine.dda_init_accumulator = val & 0xfff; + s3->videoengine.odf = (val >> 16) & 7; + s3->videoengine.yuv = !!(val & (1 << 19)); + s3->videoengine.idf = (val >> 20) & 7; + s3->videoengine.dither = !!(val & (1 << 29)); + s3->videoengine.dm_index = (val >> 23) & 7; + break; - case 0x1808c: - s3->videoengine.stretch_filt_const = val; - s3->videoengine.k2 = val & 0x7ff; - s3->videoengine.k1 = (val >> 16) & 0x7ff; - s3->videoengine.host_data = !!(val & (1 << 30)); - s3->videoengine.scale_down = !!(val & (1 << 31)); - break; + case 0x1808c: + s3->videoengine.stretch_filt_const = val; + s3->videoengine.k2 = val & 0x7ff; + s3->videoengine.k1 = (val >> 16) & 0x7ff; + s3->videoengine.host_data = !!(val & (1 << 30)); + s3->videoengine.scale_down = !!(val & (1 << 31)); + break; - case 0x18090: - s3->videoengine.src_dst_step = val; - s3->videoengine.dst_step = val & 0x1fff; - s3->videoengine.src_step = (val >> 16) & 0x1fff; - break; + case 0x18090: + s3->videoengine.src_dst_step = val; + s3->videoengine.dst_step = val & 0x1fff; + s3->videoengine.src_step = (val >> 16) & 0x1fff; + break; - case 0x18094: - s3->videoengine.crop = val; - s3->videoengine.len = val & 0xfff; - s3->videoengine.start = (val >> 16) & 0xfff; - s3->videoengine.input = 1; - break; + case 0x18094: + s3->videoengine.crop = val; + s3->videoengine.len = val & 0xfff; + s3->videoengine.start = (val >> 16) & 0xfff; + s3->videoengine.input = 1; + break; - case 0x18098: - s3->videoengine.src_base = val & 0xffffff; - break; + case 0x18098: + s3->videoengine.src_base = val & 0xffffff; + break; - case 0x1809c: - s3->videoengine.dest_base = val & 0xffffff; - break; + case 0x1809c: + s3->videoengine.dest_base = val & 0xffffff; + break; - default: - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - break; - } - } - } else { - if (addr & 0x8000) { - if (addr == 0xe2e8) { - if ((s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) - s3_accel_out_pixtrans_l(s3, val); - else { - s3_accel_write_fifo(s3, addr, val); - s3_accel_write_fifo(s3, addr + 1, val >> 8); - s3_accel_write_fifo(s3, addr + 2, val >> 16); - s3_accel_write_fifo(s3, addr + 3, val >> 24); - } - } else { + default: + break; + } + } else if (((addr & 0x1fffc) >= 0x8000) && ((addr & 0x1fffc) < 0x10000)) { + if ((addr & 0x1fffc) == 0xe2e8) { + if ((s3->chip == S3_86C928) || (s3->chip == S3_86C928PCI)) + s3_accel_out_pixtrans_l(s3, val); + else { s3_accel_write_fifo(s3, addr, val); s3_accel_write_fifo(s3, addr + 1, val >> 8); s3_accel_write_fifo(s3, addr + 2, val >> 16); s3_accel_write_fifo(s3, addr + 3, val >> 24); } } else { - s3_accel_out_pixtrans_l(s3, val); + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + s3_accel_write_fifo(s3, addr + 2, val >> 16); + s3_accel_write_fifo(s3, addr + 3, val >> 24); } } } + static void s3_vblank_start(svga_t *svga) { @@ -2145,7 +2258,7 @@ s3_hwcursor_draw(svga_t *svga, int displine) const s3_t *s3 = (s3_t *) svga->priv; int shift = 1; int width = 16; - uint16_t dat[2]; + uint16_t dat[2] = { 0, 0 }; int xx; int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; uint32_t fg; @@ -2478,7 +2591,6 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine) { const s3_t *s3 = (s3_t *) svga->priv; int offset = (s3->streams.sec_x - s3->streams.pri_x) + 1; - int h_acc = s3->streams.dda_horiz_accumulator; int r[8]; int g[8]; int b[8]; @@ -2488,7 +2600,7 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine) uint32_t *p; uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - p = &(buffer32->line[displine][offset + svga->x_add]); + p = &((uint32_t *)buffer32->line[displine])[offset + svga->x_add]; if ((offset + s3->streams.sec_w) > s3->streams.pri_w) x_size = (s3->streams.pri_w - s3->streams.sec_x) + 1; @@ -2500,13 +2612,14 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine) for (int x = 0; x < x_size; x++) { *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - h_acc += s3->streams.k1_horiz_scale; - if (h_acc >= 0) { + svga->overlay_latch.h_acc += s3->streams.k1_horiz_scale; + if (svga->overlay_latch.h_acc >= 0) { if ((x_read ^ (x_read + 1)) & ~3) OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; - h_acc += (s3->streams.k2_horiz_scale - s3->streams.k1_horiz_scale); + svga->overlay_latch.h_acc += (s3->streams.k2_horiz_scale - s3->streams.k1_horiz_scale); } } @@ -2728,16 +2841,24 @@ s3_out(uint16_t addr, uint8_t val, void *priv) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { - svga->seqregs[svga->seqaddr] = val; - switch (svga->seqaddr) { - case 0x12: - case 0x13: - svga_recalctimings(svga); - return; + if (s3->chip == S3_TRIO64V2) { + if (svga->seqaddr >= 0x10) { + svga->seqregs[svga->seqaddr] = val; + svga_recalctimings(svga); + return; + } + } else { + if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + svga->seqregs[svga->seqaddr] = val; + switch (svga->seqaddr) { + case 0x12: + case 0x13: + svga_recalctimings(svga); + return; - default: - break; + default: + break; + } } } if (svga->seqaddr == 4) /*Chain-4 - update banking*/ @@ -2770,13 +2891,15 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x3C7: case 0x3C8: case 0x3C9: + case 0x3CA: /*0x3c6 alias*/ + case 0x3CB: /*0x3c7 alias*/ rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); if (s3->chip >= S3_TRIO32) svga_out(addr, val, svga); else if ((s3->chip == S3_VISION964 && s3->card_type != S3_ELSAWIN2KPROX_964) || (s3->chip == S3_86C928)) { rs3 = !!(svga->crtc[0x55] & 0x02); bt48x_ramdac_out(addr, rs2, rs3, val, svga->ramdac, svga); - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_DIAMOND_STEALTH64_968 || s3->card_type == S3_ELSAWIN2KPROX || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) ibm_rgb528_ramdac_out(addr, rs2, val, svga->ramdac, svga); else if (s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968)) { rs3 = !!(svga->crtc[0x55] & 0x02); @@ -2808,8 +2931,6 @@ s3_out(uint16_t addr, uint8_t val, void *priv) return; if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - if ((s3->chip == S3_TRIO64V2) && (svga->crtcreg >= 0x80)) - return; if ((s3->chip <= S3_86C924) && (svga->crtcreg >= 0x50)) return; @@ -2828,6 +2949,7 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x50: s3->bpp = (svga->crtc[0x50] >> 4) & 3; + s3_log("S3 BPP=%d.\n", s3->bpp); if (s3->bpp == 3) { if (!(s3->accel.multifunc[0xe] & 0x200)) /*On True Color mode change, reset bit 4 of Misc Index register*/ s3->accel.multifunc[0xe] &= ~0x10; @@ -2957,10 +3079,12 @@ s3_out(uint16_t addr, uint8_t val, void *priv) case 0x58: case 0x59: case 0x5a: + s3_log("[%04X:%08X]: Write CRTC%02x=%02x.\n", CS, cpu_state.pc, svga->crtcreg, svga->crtc[svga->crtcreg]); s3_updatemapping(s3); break; case 0x55: + s3_log("[%04X:%08X]: Write CRTC%02x=%02x.\n", CS, cpu_state.pc, svga->crtcreg, svga->crtc[svga->crtcreg]); if (s3->chip == S3_86C928) { if (val & 0x28) { svga->hwcursor_draw = NULL; @@ -3077,7 +3201,7 @@ s3_in(uint16_t addr, void *priv) break; case 0x3c5: - if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) { + if ((svga->seqaddr >= 0x10 && svga->seqaddr < 0x20) && (s3->chip < S3_TRIO64V2)) { temp = svga->seqregs[svga->seqaddr]; /* This is needed for the Intel Advanced/ATX's built-in S3 Trio64V+ BIOS to not get stuck in an infinite loop. */ @@ -3086,13 +3210,20 @@ s3_in(uint16_t addr, void *priv) (s3->card_type == S3_CARDEX_TRIO64VPLUS)) && (svga->seqaddr == 0x17)) svga->seqregs[svga->seqaddr] ^= 0x01; return temp; - } + } if ((svga->seqaddr >= 0x10) && (s3->chip >= S3_TRIO64V2)) { + return svga->seqregs[svga->seqaddr]; + } else if ((svga->seqaddr >= 5) && (svga->seqaddr < 8)) + return 0xff; + else + return svga->seqregs[svga->seqaddr]; break; case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9: + case 0x3ca: /*0x3c6 alias*/ + case 0x3cb: /*0x3c7 alias*/ rs2 = (svga->crtc[0x55] & 0x01) || !!(svga->crtc[0x43] & 2); if (s3->chip >= S3_TRIO32) return svga_in(addr, svga); @@ -3103,7 +3234,7 @@ s3_in(uint16_t addr, void *priv) rs3 = !!(svga->crtc[0x55] & 0x02); temp = bt48x_ramdac_in(addr, rs2, rs3, svga->ramdac, svga); return temp; - } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_ELSAWIN2KPROX || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) + } else if ((s3->chip == S3_VISION964 && s3->card_type == S3_ELSAWIN2KPROX_964) || (s3->chip == S3_VISION968 && (s3->card_type == S3_DIAMOND_STEALTH64_968 || s3->card_type == S3_ELSAWIN2KPROX || s3->card_type == S3_PHOENIX_VISION968 || s3->card_type == S3_NUMBER9_9FX_771))) return ibm_rgb528_ramdac_in(addr, rs2, svga->ramdac, svga); else if (s3->chip == S3_VISION968 && (s3->card_type == S3_SPEA_MERCURY_P64V || s3->card_type == S3_MIROVIDEO40SV_ERGO_968)) { rs3 = !!(svga->crtc[0x55] & 0x02); @@ -3119,6 +3250,7 @@ s3_in(uint16_t addr, void *priv) return sc1502x_ramdac_in(addr, svga->ramdac, svga); else return sdac_ramdac_in(addr, rs2, svga->ramdac, svga); + break; case 0x3d4: return svga->crtcreg; @@ -3168,6 +3300,7 @@ s3_in(uint16_t addr, void *priv) /* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C to be mirrors of 59 and 5A. */ case 0x6b: + s3_log("[%04X:%08X]: Read CRTC6b=%02x.\n", CS, cpu_state.pc, svga->crtc[0x6b]); if (s3->chip != S3_TRIO64V2) { if (svga->crtc[0x53] & 0x08) { return (s3->chip == S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); @@ -3178,6 +3311,7 @@ s3_in(uint16_t addr, void *priv) return svga->crtc[0x6b]; break; case 0x6c: + s3_log("[%04X:%08X]: Read CRTC6c=%02x.\n", CS, cpu_state.pc, svga->crtc[0x6c]); if (s3->chip != S3_TRIO64V2) { if (svga->crtc[0x53] & 0x08) { return 0x00; @@ -3219,6 +3353,8 @@ s3_recalctimings(svga_t *svga) svga->hdisp = svga->hdisp_old; svga->ma_latch |= (s3->ma_ext << 16); + svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); + if (s3->chip >= S3_86C928) { if (svga->crtc[0x5d] & 0x01) svga->htotal |= 0x100; @@ -3232,8 +3368,8 @@ s3_recalctimings(svga_t *svga) svga->dispend |= 0x400; if (svga->crtc[0x5e] & 0x04) svga->vblankstart |= 0x400; - else - svga->vblankstart = svga->dispend; + else if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) + svga->vblankstart = svga->dispend; /*Applies only to Enhanced modes*/ if (svga->crtc[0x5e] & 0x10) svga->vsyncstart |= 0x400; if (svga->crtc[0x5e] & 0x40) @@ -3280,8 +3416,6 @@ s3_recalctimings(svga_t *svga) break; } - svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); - if (s3->chip != S3_86C801) mask |= 0x01; switch (svga->crtc[0x50] & mask) { @@ -3368,7 +3502,6 @@ s3_recalctimings(svga_t *svga) #endif if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { - svga->vram_display_mask = s3->vram_mask; s3_log("BPP=%d, pitch=%d, width=%02x, double?=%x, 16bit?=%d, highres?=%d, " "attr=%02x, hdisp=%d.\n", svga->bpp, s3->width, svga->crtc[0x50], svga->crtc[0x31] & 0x02, s3->color_16bit, s3->accel.advfunc_cntl & 4, @@ -3458,6 +3591,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 832) svga->hdisp -= 32; break; + case S3_DIAMOND_STEALTH64_968: case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: case S3_SPEA_MERCURY_P64V: @@ -3640,6 +3774,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 832) svga->hdisp -= 32; break; + case S3_DIAMOND_STEALTH64_968: case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: case S3_SPEA_MERCURY_P64V: @@ -3827,6 +3962,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 832) svga->hdisp -= 32; break; + case S3_DIAMOND_STEALTH64_968: case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: case S3_SPEA_MERCURY_P64V: @@ -3948,6 +4084,17 @@ s3_recalctimings(svga_t *svga) svga->dots_per_clock = (svga->dots_per_clock << 1) / 3; break; + case S3_VISION968: + switch (s3->card_type) { + case S3_MIROVIDEO40SV_ERGO_968: + svga->hdisp = (svga->hdisp / 3) << 2; + svga->dots_per_clock = (svga->hdisp / 3) << 2; + break; + default: + break; + } + break; + case S3_TRIO64: case S3_TRIO32: svga->hdisp /= 3; @@ -4039,6 +4186,7 @@ s3_recalctimings(svga_t *svga) if (svga->hdisp == 832) svga->hdisp -= 32; break; + case S3_DIAMOND_STEALTH64_968: case S3_NUMBER9_9FX_771: case S3_PHOENIX_VISION968: case S3_SPEA_MERCURY_P64V: @@ -4115,26 +4263,37 @@ s3_recalctimings(svga_t *svga) default: break; } + svga->vram_display_mask = s3->vram_mask; } else { - svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) { if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) { if (svga->crtc[0x31] & 0x08) { - svga->vram_display_mask = s3->vram_mask; if (svga->bpp == 8) { + if (!(svga->crtc[0x5e] & 0x04)) + svga->vblankstart = svga->dispend; /*Applies only to Enhanced modes*/ + /*Enhanced 4bpp mode, just like the 8bpp mode per the spec. */ svga->render = svga_render_8bpp_highres; svga->rowoffset <<= 1; } - } - } - } + svga->vram_display_mask = s3->vram_mask; + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; + } else + svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; } if ((s3->chip == S3_TRIO32) || (s3->chip == S3_TRIO64) || (s3->chip == S3_VISION864)) svga->hoverride = 1; else svga->hoverride = 0; + + if (svga->render == svga_render_2bpp_lowres) + svga->render = svga_render_2bpp_s3_lowres; + else if (svga->render == svga_render_2bpp_highres) + svga->render = svga_render_2bpp_s3_highres; } static void @@ -4235,7 +4394,6 @@ s3_trio64v_recalctimings(svga_t *svga) svga->lowres = (!!(svga->attrregs[0x10] & 0x40) && !(svga->crtc[0x3a] & 0x10)); if ((svga->crtc[0x3a] & 0x10) && !svga->lowres) { - svga->vram_display_mask = s3->vram_mask; switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; @@ -4262,9 +4420,9 @@ s3_trio64v_recalctimings(svga_t *svga) default: break; } + svga->vram_display_mask = s3->vram_mask; } else svga->vram_display_mask = (svga->crtc[0x32] & 0x40) ? 0x3ffff : s3->vram_mask; - } else /*Streams mode*/ { if (s3->streams.buffer_ctrl & 1) @@ -4286,20 +4444,22 @@ s3_trio64v_recalctimings(svga_t *svga) svga->overlay.addr = s3->streams.sec_fb0; svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.h_acc = s3->streams.dda_horiz_accumulator; svga->overlay.v_acc = s3->streams.dda_vert_accumulator; svga->rowoffset = s3->streams.pri_stride >> 3; - svga->vram_display_mask = s3->vram_mask; + if (svga->overlay.ena) { + svga->overlay.ena = (((s3->streams.blend_ctrl >> 24) & 7) == 0b000) || + (((s3->streams.blend_ctrl >> 24) & 7) == 0b101); + } switch ((s3->streams.pri_ctrl >> 24) & 0x7) { case 0: /*RGB-8 (CLUT)*/ svga->render = svga_render_8bpp_highres; break; case 3: /*KRGB-16 (1.5.5.5)*/ - svga->multiplier = 0.5; svga->render = svga_render_15bpp_highres; break; case 5: /*RGB-16 (5.6.5)*/ - svga->multiplier = 0.5; svga->render = svga_render_16bpp_highres; break; case 6: /*RGB-24 (8.8.8)*/ @@ -4312,9 +4472,15 @@ s3_trio64v_recalctimings(svga_t *svga) default: break; } + svga->vram_display_mask = s3->vram_mask; } svga->hoverride = 1; + + if (svga->render == svga_render_2bpp_lowres) + svga->render = svga_render_2bpp_s3_lowres; + else if (svga->render == svga_render_2bpp_highres) + svga->render = svga_render_2bpp_s3_highres; } static void @@ -4333,6 +4499,7 @@ s3_updatemapping(s3_t *s3) /*Banked framebuffer*/ if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/ { + s3_log("Enhanced Mode Mapping.\n"); /* Enhanced mode forces 64kb at 0xa0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); svga->banked_mask = 0xffff; @@ -4368,7 +4535,6 @@ s3_updatemapping(s3_t *s3) else s3->linear_base &= 0x00ffffff; } - if ((svga->crtc[0x58] & 0x10) || (s3->accel.advfunc_cntl & 0x10)) { /*Linear framebuffer*/ mem_mapping_disable(&svga->mapping); @@ -4414,7 +4580,11 @@ s3_updatemapping(s3_t *s3) else if ((s3->chip == S3_VISION968) || (s3->chip == S3_VISION868)) s3->linear_base &= 0xfe000000; - mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); + s3_log("LinearBase update=%x, size=%x.\n", s3->linear_base, s3->linear_size); + if (s3->linear_base) + mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size); + else + mem_mapping_disable(&s3->linear_mapping); } svga->fb_only = 1; } else { @@ -4430,15 +4600,19 @@ s3_updatemapping(s3_t *s3) mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000); else mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000); - } - mem_mapping_enable(&s3->mmio_mapping); + } else + mem_mapping_enable(&s3->mmio_mapping); } else { mem_mapping_disable(&s3->mmio_mapping); } /* New MMIO. */ - if (svga->crtc[0x53] & 0x08) - mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); + if (svga->crtc[0x53] & 0x08) { + if (s3->linear_base) + mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000); + else + mem_mapping_disable(&s3->new_mmio_mapping); + } else mem_mapping_disable(&s3->new_mmio_mapping); } @@ -4484,11 +4658,12 @@ s3_accel_out(uint16_t port, uint8_t val, void *priv) case 0x4148: case 0x42e8: s3->subsys_stat &= ~val; + s3->accel.subsys_cntl = (s3->accel.subsys_cntl & 0xff00) | val; s3_update_irqs(s3); break; case 0x4149: case 0x42e9: - s3->subsys_cntl = val; + s3->accel.subsys_cntl = (s3->accel.subsys_cntl & 0xff) | (val << 8); s3_update_irqs(s3); break; case 0x4548: @@ -4560,7 +4735,7 @@ s3_accel_in(uint16_t port, void *priv) return s3->subsys_stat; case 0x4149: case 0x42e9: - return s3->subsys_cntl; + return s3->accel.subsys_cntl >> 8; case 0x8148: case 0x82e8: @@ -4632,6 +4807,8 @@ s3_accel_in(uint16_t port, void *priv) case 0x9548: case 0x96e8: if (s3->chip >= S3_86C928) { + if (s3_enable_fifo(s3)) + s3_wait_fifo_idle(s3); return s3->accel.maj_axis_pcnt & 0xff; } break; @@ -4710,6 +4887,7 @@ s3_accel_in(uint16_t port, void *priv) s3->data_available = 0; } } + s3_log("FIFO Status Temp=%02x.\n", temp); return temp; case 0x9d48: @@ -4734,9 +4912,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color >> 16; + else + temp2 = s3->accel.bkgd_color & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 16; + else + temp2 = s3->accel.bkgd_color & 0xff; + } + } else temp2 = s3->accel.bkgd_color & 0xff; return temp2; @@ -4747,13 +4936,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color >> 24; + else + temp2 = s3->accel.bkgd_color >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.bkgd_color >> 24; + else + temp2 = s3->accel.bkgd_color >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.bkgd_color >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -4761,32 +4971,51 @@ s3_accel_in(uint16_t port, void *priv) case 0xa2ea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color & 0xff; - else - temp2 = s3->accel.bkgd_color >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.bkgd_color >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color & 0xff; + else + temp2 = s3->accel.bkgd_color >> 16; + } return temp2; case 0xa14b: case 0xa2eb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.bkgd_color >> 8; - else + + if (s3->accel.multifunc[0xe] & 0x200) temp2 = s3->accel.bkgd_color >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.bkgd_color >> 8; + else + temp2 = s3->accel.bkgd_color >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xa548: case 0xa6e8: if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color >> 16; + else + temp2 = s3->accel.frgd_color & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 16; + else + temp2 = s3->accel.frgd_color & 0xff; + } + } else temp2 = s3->accel.frgd_color & 0xff; return temp2; @@ -4797,13 +5026,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color >> 24; + else + temp2 = s3->accel.frgd_color >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.frgd_color >> 24; + else + temp2 = s3->accel.frgd_color >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.frgd_color >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -4811,23 +5061,31 @@ s3_accel_in(uint16_t port, void *priv) case 0xa6ea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color & 0xff; - else - temp2 = s3->accel.frgd_color >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.frgd_color >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color & 0xff; + else + temp2 = s3->accel.frgd_color >> 16; + } return temp2; case 0xa54b: case 0xa6eb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.frgd_color >> 8; - else + + if (s3->accel.multifunc[0xe] & 0x200) temp2 = s3->accel.frgd_color >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.frgd_color >> 8; + else + temp2 = s3->accel.frgd_color >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xa948: @@ -4835,9 +5093,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask >> 16; + else + temp2 = s3->accel.wrt_mask & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 16; + else + temp2 = s3->accel.wrt_mask & 0xff; + } + } else temp2 = s3->accel.wrt_mask & 0xff; return temp2; @@ -4848,13 +5117,34 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask >> 24; + else + temp2 = s3->accel.wrt_mask >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.wrt_mask >> 24; + else + temp2 = s3->accel.wrt_mask >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.wrt_mask >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } return temp2; } break; @@ -4862,23 +5152,31 @@ s3_accel_in(uint16_t port, void *priv) case 0xaaea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask & 0xff; - else - temp2 = s3->accel.wrt_mask >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.wrt_mask >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask & 0xff; + else + temp2 = s3->accel.wrt_mask >> 16; + } return temp2; case 0xa94b: case 0xaaeb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.wrt_mask >> 8; - else + + if (s3->accel.multifunc[0xe] & 0x200) temp2 = s3->accel.wrt_mask >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.wrt_mask >> 8; + else + temp2 = s3->accel.wrt_mask >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xad48: @@ -4886,9 +5184,20 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask >> 16; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask >> 16; + else + temp2 = s3->accel.rd_mask & 0xff; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 16; + else + temp2 = s3->accel.rd_mask & 0xff; + } + } else temp2 = s3->accel.rd_mask & 0xff; return temp2; @@ -4899,13 +5208,35 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask >> 24; - else + + if (s3->bpp == 3) { + if (s3->chip < S3_VISION964) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask >> 24; + else + temp2 = s3->accel.rd_mask >> 8; + + s3->accel.multifunc[0xe] ^= 0x10; + } else { + if ((s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) + temp2 = s3->accel.rd_mask >> 24; + else + temp2 = s3->accel.rd_mask >> 8; + + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } else { temp2 = s3->accel.rd_mask >> 8; - if (!(s3->accel.multifunc[0xe] & 0x200)) - s3->accel.multifunc[0xe] ^= 0x10; + if (s3->chip < S3_VISION964) + s3->accel.multifunc[0xe] ^= 0x10; + else { + if (!(s3->accel.multifunc[0xe] & 0x200)) + s3->accel.multifunc[0xe] ^= 0x10; + } + } + return temp2; } break; @@ -4913,23 +5244,31 @@ s3_accel_in(uint16_t port, void *priv) case 0xaeea: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask & 0xff; - else - temp2 = s3->accel.rd_mask >> 16; + if (s3->accel.multifunc[0xe] & 0x200) + temp2 = s3->accel.rd_mask >> 16; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask & 0xff; + else + temp2 = s3->accel.rd_mask >> 16; + } return temp2; case 0xad4b: case 0xaeeb: if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - if ((s3->bpp == 3) && (s3->accel.multifunc[0xe] & 0x10) && !(s3->accel.multifunc[0xe] & 0x200)) - temp2 = s3->accel.rd_mask >> 8; - else + + if (s3->accel.multifunc[0xe] & 0x200) temp2 = s3->accel.rd_mask >> 24; + else if (s3->bpp == 3) { + if (s3->accel.multifunc[0xe] & 0x10) + temp2 = s3->accel.rd_mask >> 8; + else + temp2 = s3->accel.rd_mask >> 24; - if (!(s3->accel.multifunc[0xe] & 0x200)) s3->accel.multifunc[0xe] ^= 0x10; + } return temp2; case 0xb148: @@ -5006,33 +5345,58 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - switch (temp) { - case 0x0: - return s3->accel.multifunc[0x0] & 0xff; - case 0x1: - return s3->accel.multifunc[0x1] & 0xff; - case 0x2: - return s3->accel.multifunc[0x2] & 0xff; - case 0x3: - return s3->accel.multifunc[0x3] & 0xff; - case 0x4: - return s3->accel.multifunc[0x4] & 0xff; - case 0x5: - return s3->accel.multifunc[0xa] & 0xff; - case 0x6: - return s3->accel.multifunc[0xe] & 0xff; - case 0x7: - return s3->accel.cmd & 0xff; - case 0x8: - return s3->accel.subsys_cntl & 0xff; - case 0x9: - return s3->accel.setup_md & 0xff; - case 0xa: - return s3->accel.multifunc[0xd] & 0xff; + if (s3->chip >= S3_VISION964) { + temp = s3->accel.multifunc[0xf] & 0xf; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] & 0xff; + case 0x1: + return s3->accel.multifunc[0x1] & 0xff; + case 0x2: + return s3->accel.multifunc[0x2] & 0xff; + case 0x3: + return s3->accel.multifunc[0x3] & 0xff; + case 0x4: + return s3->accel.multifunc[0x4] & 0xff; + case 0x5: + return s3->accel.multifunc[0xa] & 0xff; + case 0x6: + return s3->accel.multifunc[0xe] & 0xff; + case 0x7: + return s3->accel.cmd & 0xff; + case 0x8: + return s3->accel.subsys_cntl & 0xff; + case 0x9: + return s3->accel.setup_md & 0xff; + case 0xa: + return s3->accel.multifunc[0xd] & 0xff; - default: - break; + default: + break; + } + } else { + temp = s3->accel.multifunc[0xf] & 7; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] & 0xff; + case 0x1: + return s3->accel.multifunc[0x1] & 0xff; + case 0x2: + return s3->accel.multifunc[0x2] & 0xff; + case 0x3: + return s3->accel.multifunc[0x3] & 0xff; + case 0x4: + return s3->accel.multifunc[0x4] & 0xff; + case 0x5: + return s3->accel.multifunc[0xa] & 0xff; + case 0x6: + return s3->accel.multifunc[0xe] & 0xff; + case 0x7: + return s3->accel.cmd & 0xff; + + default: + break; + } } return 0xff; } @@ -5042,34 +5406,60 @@ s3_accel_in(uint16_t port, void *priv) if (s3->chip >= S3_86C928) { if (s3_enable_fifo(s3)) s3_wait_fifo_idle(s3); - temp = s3->accel.multifunc[0xf] & 0xf; - s3->accel.multifunc[0xf]++; - switch (temp) { - case 0x0: - return s3->accel.multifunc[0x0] >> 8; - case 0x1: - return s3->accel.multifunc[0x1] >> 8; - case 0x2: - return s3->accel.multifunc[0x2] >> 8; - case 0x3: - return s3->accel.multifunc[0x3] >> 8; - case 0x4: - return s3->accel.multifunc[0x4] >> 8; - case 0x5: - return s3->accel.multifunc[0xa] >> 8; - case 0x6: - return s3->accel.multifunc[0xe] >> 8; - case 0x7: - return s3->accel.cmd >> 8; - case 0x8: - return (s3->accel.subsys_cntl >> 8) & ~0xe000; - case 0x9: - return (s3->accel.setup_md >> 8) & ~0xf000; - case 0xa: - return s3->accel.multifunc[0xd] >> 8; + if (s3->chip >= S3_VISION964) { + temp = s3->accel.multifunc[0xf] & 0xf; + s3->accel.multifunc[0xf] = (s3->accel.multifunc[0xf] + 1) & 0xf; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] >> 8; + case 0x1: + return s3->accel.multifunc[0x1] >> 8; + case 0x2: + return s3->accel.multifunc[0x2] >> 8; + case 0x3: + return s3->accel.multifunc[0x3] >> 8; + case 0x4: + return s3->accel.multifunc[0x4] >> 8; + case 0x5: + return s3->accel.multifunc[0xa] >> 8; + case 0x6: + return s3->accel.multifunc[0xe] >> 8; + case 0x7: + return s3->accel.cmd >> 8; + case 0x8: + return (s3->accel.subsys_cntl >> 8) & ~0xe000; + case 0x9: + return (s3->accel.setup_md >> 8) & ~0xf000; + case 0xa: + return s3->accel.multifunc[0xd] >> 8; - default: - break; + default: + break; + } + } else { + temp = s3->accel.multifunc[0xf] & 7; + s3->accel.multifunc[0xf] = (s3->accel.multifunc[0xf] + 1) & 7; + switch (temp) { + case 0x0: + return s3->accel.multifunc[0x0] >> 8; + case 0x1: + return s3->accel.multifunc[0x1] >> 8; + case 0x2: + return s3->accel.multifunc[0x2] >> 8; + case 0x3: + return s3->accel.multifunc[0x3] >> 8; + case 0x4: + return s3->accel.multifunc[0x4] >> 8; + case 0x5: + return s3->accel.multifunc[0xa] >> 8; + case 0x6: + return s3->accel.multifunc[0xe] >> 8; + case 0x7: + return s3->accel.cmd >> 8; + + default: + break; + } } return 0xff; } @@ -5211,7 +5601,7 @@ s3_accel_in(uint16_t port, void *priv) case 0xe2e8: if (!s3_cpu_dest(s3)) break; - READ_PIXTRANS_BYTE_IO(0) + READ_PIXTRANS_BYTE_IO(0); if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: @@ -5293,7 +5683,7 @@ s3_accel_in(uint16_t port, void *priv) case 0xe2eb: if (!s3_cpu_dest(s3)) break; - READ_PIXTRANS_BYTE_IO(3) + READ_PIXTRANS_BYTE_IO(3); if (s3->accel.cmd & 0x100) { switch (s3->accel.cmd & 0x600) { case 0x000: @@ -5307,12 +5697,23 @@ s3_accel_in(uint16_t port, void *priv) break; case 0x200: if (((s3->accel.multifunc[0xa] & 0xc0) == 0x80) || (s3->accel.cmd & 2)) { - if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) - s3->accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + if (((s3->accel.frgd_mix & 0x60) != 0x40) || ((s3->accel.bkgd_mix & 0x60) != 0x40)) { + if (s3->accel.cmd & 0x1000) + s3->accel_start(16, 1, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), 0, s3); + else + s3->accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3); + } else { + if (s3->accel.cmd & 0x1000) + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); + else + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } + } else { + if (s3->accel.cmd & 0x1000) + s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[3] | (s3->accel.pix_trans[2] << 8) | (s3->accel.pix_trans[1] << 16) | (s3->accel.pix_trans[0] << 24), s3); else s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); - } else - s3->accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3); + } break; default: @@ -5451,15 +5852,40 @@ s3_accel_write(uint32_t addr, uint8_t val, void *priv) { s3_t *s3 = (s3_t *) priv; const svga_t *svga = &s3->svga; + uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff; if (!s3->enable_8514) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_BYTE); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE); + if ((addr & addr_mask) < 0x8000) { + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_BYTE); + } else { + switch (addr & addr_mask) { + case 0x83b0 ... 0x83df: + s3_out(addr & 0x3ff, val, s3); + break; + case 0x8504: + s3->subsys_stat &= ~val; + s3_update_irqs(s3); + break; + case 0x8505: + s3->subsys_cntl = val; + s3_update_irqs(s3); + break; + case 0x850c: + s3->accel.advfunc_cntl = val; + s3_updatemapping(s3); + break; + case 0xff20: + s3->serialport = val; + i2c_gpio_set(s3->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); + break; + default: + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_BYTE); + break; + } + } } else s3_accel_write_fifo(s3, addr & 0xffff, val); } @@ -5469,15 +5895,28 @@ s3_accel_write_w(uint32_t addr, uint16_t val, void *priv) { s3_t *s3 = (s3_t *) priv; const svga_t *svga = &s3->svga; + uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff; if (!s3->enable_8514) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_WORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD); + if ((addr & (addr_mask - 1)) < 0x8000) { + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_WORD); + } else { + switch (addr & (addr_mask - 1)) { + case 0x83d4: + s3_accel_write_fifo(s3, addr, val); + s3_accel_write_fifo(s3, addr + 1, val >> 8); + break; + case 0xff20: + s3_accel_write_fifo(s3, addr, val); + break; + default: + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_WORD); + break; + } + } } else s3_accel_write_fifo_w(s3, addr & 0xffff, val); } @@ -5486,16 +5925,162 @@ static void s3_accel_write_l(uint32_t addr, uint32_t val, void *priv) { s3_t *s3 = (s3_t *) priv; - const svga_t *svga = &s3->svga; + svga_t *svga = &s3->svga; + uint32_t addr_mask = (svga->crtc[0x53] & 0x08) ? 0x1ffff : 0xffff; if (!s3->enable_8514) return; if (s3_enable_fifo(s3)) { - if (svga->crtc[0x53] & 0x08) - s3_queue(s3, addr & 0x1ffff, val, FIFO_WRITE_DWORD); - else - s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD); + if ((addr & (addr_mask - 3)) < 0x8000) { + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_DWORD); + } else { + switch (addr & (addr_mask - 3)) { + case 0x8180: + s3->streams.pri_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x8184: + s3->streams.chroma_ctrl = val; + break; + case 0x8190: + s3->streams.sec_ctrl = val; + s3->streams.dda_horiz_accumulator = val & 0xfff; + if (val & 0x1000) + s3->streams.dda_horiz_accumulator |= ~0xfff; + + s3->streams.sdif = (val >> 24) & 7; + break; + case 0x8194: + s3->streams.chroma_upper_bound = val; + break; + case 0x8198: + s3->streams.sec_filter = val; + s3->streams.k1_horiz_scale = val & 0x7ff; + if (val & 0x800) + s3->streams.k1_horiz_scale |= ~0x7ff; + + s3->streams.k2_horiz_scale = (val >> 16) & 0x7ff; + if ((val >> 16) & 0x800) + s3->streams.k2_horiz_scale |= ~0x7ff; + + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81a0: + s3->streams.blend_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81c0: + s3->streams.pri_fb0 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81c4: + s3->streams.pri_fb1 = val & 0x3fffff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81c8: + s3->streams.pri_stride = val & 0xfff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81cc: + s3->streams.buffer_ctrl = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81d0: + s3->streams.sec_fb0 = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81d4: + s3->streams.sec_fb1 = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81d8: + s3->streams.sec_stride = val; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81dc: + s3->streams.overlay_ctrl = val; + break; + case 0x81e0: + s3->streams.k1_vert_scale = val & 0x7ff; + if (val & 0x800) + s3->streams.k1_vert_scale |= ~0x7ff; + break; + case 0x81e4: + s3->streams.k2_vert_scale = val & 0x7ff; + if (val & 0x800) + s3->streams.k2_vert_scale |= ~0x7ff; + break; + case 0x81e8: + s3->streams.dda_vert_accumulator = val & 0xfff; + if (val & 0x1000) + s3->streams.dda_vert_accumulator |= ~0xfff; + + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81ec: + s3->streams.fifo_ctrl = val; + break; + case 0x81f0: + s3->streams.pri_start = val; + s3->streams.pri_x = (val >> 16) & 0x7ff; + s3->streams.pri_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81f4: + s3->streams.pri_size = val; + s3->streams.pri_w = (val >> 16) & 0x7ff; + s3->streams.pri_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81f8: + s3->streams.sec_start = val; + s3->streams.sec_x = (val >> 16) & 0x7ff; + s3->streams.sec_y = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + case 0x81fc: + s3->streams.sec_size = val; + s3->streams.sec_w = (val >> 16) & 0x7ff; + s3->streams.sec_h = val & 0x7ff; + svga_recalctimings(svga); + svga->fullchange = svga->monitor->mon_changeframecount;; + break; + + case 0x8504: + s3->subsys_stat &= ~(val & 0xff); + s3->subsys_cntl = (val >> 8); + s3_update_irqs(s3); + break; + + case 0x850c: + s3->accel.advfunc_cntl = val & 0xff; + s3_updatemapping(s3); + break; + + case 0xff20: + s3_accel_write_fifo(s3, addr, val); + break; + + default: + s3_queue(s3, addr & addr_mask, val, FIFO_WRITE_DWORD); + break; + } + } } else s3_accel_write_fifo_l(s3, addr & 0xffff, val); } @@ -7733,9 +8318,8 @@ s3_911_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, } } - if ((s3->accel.cmd & 0x100) && !cpu_input) { + if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/ - } frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; @@ -7924,12 +8508,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi uint32_t *vram_l = (uint32_t *) svga->vram; uint32_t compare = s3->accel.color_cmp; uint8_t rop = s3->accel.ropmix & 0xff; - int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3; uint32_t rd_mask = s3->accel.rd_mask; uint32_t wrt_mask = s3->accel.wrt_mask; uint32_t frgd_color = s3->accel.frgd_color; uint32_t bkgd_color = s3->accel.bkgd_color; int cmd = s3->accel.cmd >> 13; + int update = 1; uint32_t srcbase; uint32_t dstbase; @@ -8012,6 +8596,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi /*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled. When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on the NOP command)*/ + s3_log("CMD=%d, full=%04x, s3bpp=%x, multifuncE=%03x, sourcedisplay=%x, mmio=%02x, srcbase=%08x, dstbase=%08x.\n", cmd, s3->accel.cmd, s3->bpp, s3->accel.multifunc[0x0e] & 0x230, vram_mask, svga->crtc[0x53] & 0x18, srcbase, dstbase); switch (cmd) { case 0: /*NOP (Short Stroke Vectors)*/ if (s3->accel.ssv_state == 0) @@ -8042,7 +8627,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8140,7 +8740,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8229,7 +8844,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8318,9 +8948,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (s3->accel.b2e8_pix && s3_cpu_src(s3) && count == 16) { /*Stupid undocumented 0xB2E8 on 911/924*/ + if (s3->accel.b2e8_pix && s3_cpu_src(s3) && (count == 16)) { /*Stupid undocumented 0xB2E8 on 911/924*/ count = s3->accel.maj_axis_pcnt + 1; s3->accel.temp_cnt = 16; + s3_log("CMD2: B2E8 pixtrans, frgdmix=%d, bkgdmix=%d.\n", frgd_mix, bkgd_mix); } while (count-- && s3->accel.sy >= 0) { @@ -8329,7 +8960,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.temp_cnt = 16; } - if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { + if ((((s3->accel.cx) >= clip_l && (s3->accel.cx) <= clip_r && (s3->accel.cy) >= clip_t && (s3->accel.cy) <= clip_b) && !(s3->accel.multifunc[0xe] & 0x20)) || + (((s3->accel.cx) < clip_l && (s3->accel.cx) > clip_r && (s3->accel.cy) < clip_t && (s3->accel.cy) > clip_b) && (s3->accel.multifunc[0xe] & 0x20)) ) { if (s3_cpu_dest(s3) && ((s3->accel.multifunc[0xa] & 0xc0) == 0x00)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ } else if (s3_cpu_dest(s3) && vram_mask) { @@ -8363,7 +8995,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.cx, dest_dat); MIX @@ -8399,11 +9046,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); else - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; + if (s3->accel.cmd & 0x80) s3->accel.cy++; else @@ -8473,7 +9121,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); MIX @@ -8508,11 +9171,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cur_x = s3->accel.poly_cx & 0xfff; s3->accel.cur_y = s3->accel.poly_cy & 0xfff; s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff; - s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff; + s3->accel.cur_y2 = s3->accel.poly_cy2 & 0xfff; } break; - case 6: /*BitBlt*/ + case 6: /*BitBlt*/ if (!cpu_input) { /*!cpu_input is trigger to start operation*/ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; s3->accel.sy = s3->accel.multifunc[0] & 0xfff; @@ -8534,15 +9197,17 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi frgd_mix = (s3->accel.frgd_mix >> 5) & 3; bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; - if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode && (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7 && (s3->accel.bkgd_mix & 0xf) == 7) { + if (!cpu_input && (frgd_mix == 3) && !vram_mask && !(s3->accel.multifunc[0xe] & 0x100) && ((s3->accel.cmd & 0xa0) == 0xa0) && ((s3->accel.frgd_mix & 0xf) == 7) && ((s3->accel.bkgd_mix & 0xf) == 7)) { while (1) { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && (s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b) { READ(s3->accel.src + s3->accel.cx, src_dat); READ(s3->accel.dest + s3->accel.dx, dest_dat); dest_dat = (src_dat & wrt_mask) | (dest_dat & ~wrt_mask); - WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + if (s3->accel.cmd & 0x10) { + WRITE(s3->accel.dest + s3->accel.dx, dest_dat); + } } s3->accel.cx++; @@ -8557,7 +9222,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy++; s3->accel.dy++; - s3->accel.dy &= 0xfff; s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -8572,7 +9236,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } else { while (count-- && s3->accel.sy >= 0) { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && ((s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)) { + if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { READ(s3->accel.src + s3->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); @@ -8598,7 +9262,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); MIX @@ -8643,7 +9322,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi s3->accel.cy--; s3->accel.dy--; } - s3->accel.dy &= 0xfff; s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -8692,7 +9370,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3; while (count-- && s3->accel.sy >= 0) { - if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b) { + if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && (s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b) { if (vram_mask) { READ(s3->accel.src + s3->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); @@ -8718,7 +9396,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); MIX @@ -8809,7 +9502,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { src_dat = s3->accel.frgd_color; - if (((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) && (s3->accel.cmd & 0x10)) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8843,7 +9551,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r && (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b) { src_dat = s3->accel.frgd_color; - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat); MIX @@ -8932,7 +9655,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi break; } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.poly_x, dest_dat); MIX @@ -9065,7 +9803,22 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, voi } } - if ((compare_mode == 2 && src_dat != compare) || (compare_mode == 3 && src_dat == compare) || compare_mode < 2) { + if (s3->accel.multifunc[0xe] & 0x100) { + if (s3->accel.multifunc[0xe] & 0x80) { + if (src_dat != compare) + update = 0; + else + update = 1; + } else { + if (src_dat == compare) + update = 0; + else + update = 1; + } + } else + update = 1; + + if (update) { READ(s3->accel.dest + s3->accel.dx, dest_dat); ROPMIX @@ -9156,18 +9909,19 @@ s3_pci_read(UNUSED(int func), int addr, void *priv) return s3->pci_regs[PCI_REG_COMMAND] | 0x80; /*Respond to IO and memory accesses*/ else return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/ - break; + break; case 0x07: return (s3->chip == S3_TRIO64V2) ? (s3->pci_regs[0x07] & 0x36) : (1 << 1); /*Medium DEVSEL timing*/ - case 0x08: switch (s3->chip) { /*Revision ID*/ - case S3_TRIO64V: - return 0x40; - case S3_TRIO64V2: - return 0x16; /*Confirmed on an onboard 64V2/DX*/ - default: - return 0x00; + case 0x08: + switch (s3->chip) { /*Revision ID*/ + case S3_TRIO64V: + return 0x40; + case S3_TRIO64V2: + return 0x16; /*Confirmed on an onboard 64V2/DX*/ + default: + return 0x00; } break; case 0x09: @@ -9178,33 +9932,24 @@ s3_pci_read(UNUSED(int func), int addr, void *priv) return 0x00; /*Supports VGA interface*/ else return 0x01; + break; case 0x0b: if (s3->chip >= S3_TRIO32 || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) return 0x03; else return 0x00; + break; case 0x0d: return (s3->chip == S3_TRIO64V2) ? (s3->pci_regs[0x0d] & 0xf8) : 0x00; - case 0x10: - return 0x00; /*Linear frame buffer address*/ - case 0x11: - return 0x00; case 0x12: - if (svga->crtc[0x53] & 0x08) - return 0x00; - else - return (svga->crtc[0x5a] & 0x80); - break; + return ((s3->chip == S3_VISION868) || (s3->chip == S3_VISION968) || (s3->chip >= S3_TRIO64V)) ? 0x00 : + (svga->crtc[0x5a] & 0x80); case 0x13: - if (svga->crtc[0x53] & 0x08) { - return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe); - } else { - return svga->crtc[0x59]; - } - break; + return ((s3->chip == S3_VISION868) || (s3->chip == S3_VISION968) || (s3->chip >= S3_TRIO64V)) ? + (svga->crtc[0x59] & 0xfc) : svga->crtc[0x59]; case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/ @@ -9254,17 +9999,22 @@ s3_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case PCI_REG_COMMAND: - if (val & PCI_COMMAND_IO) + if (val & PCI_COMMAND_IO) { s3_io_set(s3); - else + } else s3_io_remove(s3); - s3->pci_regs[PCI_REG_COMMAND] = (val & 0x23); + + if (s3->chip >= S3_TRIO64V) + s3->pci_regs[PCI_REG_COMMAND] = (val & 0x27); + else + s3->pci_regs[PCI_REG_COMMAND] = (val & 0x23); + s3_updatemapping(s3); - break; + return; case 0x07: if (s3->chip == S3_TRIO64V2) { - s3->pci_regs[0x07] = val & 0x3e; + s3->pci_regs[0x07] &= ~(val & 0x30); return; } break; @@ -9277,18 +10027,14 @@ s3_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) break; case 0x12: - if (!(svga->crtc[0x53] & 0x08)) { - svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80); + if (s3->chip < S3_TRIO64V) { + svga->crtc[0x5a] = val & 0x80; s3_updatemapping(s3); } break; case 0x13: - if (svga->crtc[0x53] & 0x08) { - svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : (val & 0xfe); - } else { - svga->crtc[0x59] = val; - } + svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : val; s3_updatemapping(s3); break; @@ -9383,156 +10129,49 @@ static int vram_sizes[] = { }; static void -s3_reset(void *priv) +s3_disable_handlers(s3_t *s3) { - s3_t *s3 = (s3_t *) priv; - svga_t *svga = &s3->svga; - - memset(svga->crtc, 0x00, sizeof(svga->crtc)); - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000ULL << 32; - svga->dispofftime = 1000ULL << 32; - svga->bpp = 8; - if (s3->pci) - svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4); - else if (s3->vlb) - svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4); - else - svga->crtc[0x36] = 3 | (1 << 4); - - if (s3->chip >= S3_86C928) - svga->crtc[0x36] |= (vram_sizes[s3->vram] << 5); - else - svga->crtc[0x36] |= ((s3->vram == 1) ? 0x00 : 0x20) | 0x80; - - svga->crtc[0x37] = 1 | (7 << 5); - - if (s3->chip >= S3_86C928) - svga->crtc[0x37] |= 0x04; - - s3_io_set(s3); - - memset(s3->pci_regs, 0x00, 256); - - s3->pci_regs[PCI_REG_COMMAND] = 7; - - s3->pci_regs[0x30] = 0x00; - s3->pci_regs[0x32] = 0x0c; - s3->pci_regs[0x33] = 0x00; - - if (s3->chip <= S3_86C924) - s3->accel_start = s3_911_accel_start; - else - s3->accel_start = s3_accel_start; - - switch (s3->card_type) { - case S3_MIROCRYSTAL8S_805: - case S3_MIROCRYSTAL10SD_805: - svga->crtc[0x5a] = 0x0a; - svga->getclock = sdac_getclock; - break; - - case S3_SPEA_MIRAGE_86C801: - case S3_SPEA_MIRAGE_86C805: - svga->crtc[0x5a] = 0x0a; - break; - - case S3_PHOENIX_86C801: - case S3_PHOENIX_86C805: - svga->crtc[0x5a] = 0x0a; - break; - - case S3_METHEUS_86C928: - case S3_SPEA_MERCURY_LITE_PCI: - svga->crtc[0x5a] = 0x0a; - break; - - case S3_PARADISE_BAHAMAS64: - case S3_PHOENIX_VISION864: - case S3_MIROCRYSTAL20SD_864: - svga->crtc[0x5a] = 0x0a; - break; + s3_io_remove(s3); - case S3_DIAMOND_STEALTH64_964: - case S3_ELSAWIN2KPROX_964: - case S3_MIROCRYSTAL20SV_964: - svga->crtc[0x5a] = 0x0a; - break; - - case S3_ELSAWIN2KPROX: - case S3_SPEA_MERCURY_P64V: - case S3_MIROVIDEO40SV_ERGO_968: - case S3_NUMBER9_9FX_771: - case S3_PHOENIX_VISION968: - if (s3->pci) { - svga->crtc[0x53] = 0x18; - svga->crtc[0x58] = 0x10; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - } else { - svga->crtc[0x53] = 0x00; - svga->crtc[0x59] = 0x00; - svga->crtc[0x5a] = 0x0a; - } - break; + mem_mapping_disable(&s3->linear_mapping); + mem_mapping_disable(&s3->mmio_mapping); + mem_mapping_disable(&s3->new_mmio_mapping); + mem_mapping_disable(&s3->svga.mapping); + if (s3->pci) + mem_mapping_disable(&s3->bios_rom.mapping); - case S3_NUMBER9_9FX_531: - case S3_PHOENIX_VISION868: - if (s3->pci) { - svga->crtc[0x53] = 0x18; - svga->crtc[0x58] = 0x10; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - } else { - svga->crtc[0x53] = 0x00; - svga->crtc[0x59] = 0x00; - svga->crtc[0x5a] = 0x0a; - } - break; + /* Save all the mappings and the timers because they are part of linked lists. */ + reset_state->linear_mapping = s3->linear_mapping; + reset_state->mmio_mapping = s3->mmio_mapping; + reset_state->new_mmio_mapping = s3->new_mmio_mapping; + reset_state->svga.mapping = s3->svga.mapping; + reset_state->bios_rom.mapping = s3->bios_rom.mapping; - case S3_PHOENIX_TRIO64: - case S3_PHOENIX_TRIO64_ONBOARD: - case S3_STB_POWERGRAPH_64_VIDEO: - case S3_CARDEX_TRIO64VPLUS: - case S3_PHOENIX_TRIO64VPLUS: - case S3_PHOENIX_TRIO64VPLUS_ONBOARD: - case S3_DIAMOND_STEALTH64_764: - case S3_SPEA_MIRAGE_P64: - case S3_NUMBER9_9FX: - if (s3->chip == S3_TRIO64V) - svga->crtc[0x53] = 0x08; - break; + reset_state->svga.timer = s3->svga.timer; + reset_state->svga.timer8514 = s3->svga.timer8514; - case S3_TRIO64V2_DX: - svga->crtc[0x53] = 0x08; - svga->crtc[0x59] = 0x70; - svga->crtc[0x5a] = 0x00; - svga->crtc[0x6c] = 1; - s3->pci_regs[0x05] = 0; - s3->pci_regs[0x06] = 0; - s3->pci_regs[0x07] = 2; - s3->pci_regs[0x3d] = 1; - s3->pci_regs[0x3e] = 4; - s3->pci_regs[0x3f] = 0xff; - break; + memset(s3->svga.vram, 0x00, s3->svga.vram_max + 8); + memset(s3->svga.changedvram, 0x00, (s3->svga.vram_max >> 12) + 1); +} - default: - break; - } +static void +s3_reset(void *priv) +{ + s3_t *s3 = (s3_t *) priv; - if (s3->has_bios) { + if (reset_state != NULL) { + s3->accel.multifunc[0xe] &= ~(0x200 | 0x10); + s3_disable_handlers(s3); + s3->force_busy = 0; + s3->blitter_busy = 0; + s3->fifo_read_idx = 0; + s3->fifo_write_idx = 0; if (s3->pci) - mem_mapping_disable(&s3->bios_rom.mapping); - } - - s3_updatemapping(s3); + reset_state->pci_slot = s3->pci_slot; - mem_mapping_disable(&s3->mmio_mapping); - mem_mapping_disable(&s3->new_mmio_mapping); + *s3 = *reset_state; + } } static void * @@ -9541,8 +10180,9 @@ s3_init(const device_t *info) const char *bios_fn; int chip; int stepping; - s3_t *s3 = malloc(sizeof(s3_t)); - svga_t *svga = &s3->svga; + s3_t *s3 = calloc(1, sizeof(s3_t)); + reset_state = calloc(1, sizeof(s3_t)); + svga_t *svga = &s3->svga; int vram; uint32_t vram_size; @@ -9639,10 +10279,7 @@ s3_init(const device_t *info) case S3_PHOENIX_VISION868: bios_fn = ROM_PHOENIX_VISION868; chip = S3_VISION868; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision868_pci); break; case S3_DIAMOND_STEALTH64_964: bios_fn = ROM_DIAMOND_STEALTH64_964; @@ -9662,6 +10299,14 @@ s3_init(const device_t *info) video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision964_vlb); } break; + case S3_DIAMOND_STEALTH64_968: + bios_fn = ROM_DIAMOND_STEALTH64_968; + chip = S3_VISION968; + if (info->flags & DEVICE_PCI) + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); + else + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); + break; case S3_MIROVIDEO40SV_ERGO_968: bios_fn = ROM_MIROVIDEO40SV_ERGO_968_PCI; chip = S3_VISION968; @@ -9675,10 +10320,7 @@ s3_init(const device_t *info) case S3_PHOENIX_VISION968: bios_fn = ROM_PHOENIX_VISION968; chip = S3_VISION968; - if (info->flags & DEVICE_PCI) - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_vlb); + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_s3_vision968_pci); break; case S3_ELSAWIN2KPROX_964: bios_fn = ROM_ELSAWIN2KPROX_964; @@ -9800,14 +10442,13 @@ s3_init(const device_t *info) return NULL; } - memset(s3, 0, sizeof(s3_t)); - vram = device_get_config_int("memory"); if (vram) vram_size = vram << 20; else vram_size = 512 << 10; + s3->vram_mask = vram_size - 1; s3->vram = vram; @@ -9843,7 +10484,7 @@ s3_init(const device_t *info) mem_mapping_disable(&s3->mmio_mapping); mem_mapping_disable(&s3->new_mmio_mapping); - if (chip == S3_VISION964 || chip == S3_VISION968) + if ((chip == S3_VISION964) || (chip == S3_VISION968)) svga_init(info, &s3->svga, s3, vram_size, s3_recalctimings, s3_in, s3_out, @@ -9881,16 +10522,14 @@ s3_init(const device_t *info) case S3_VISION968: switch (info->local) { + case S3_DIAMOND_STEALTH64_968: case S3_ELSAWIN2KPROX: case S3_PHOENIX_VISION968: case S3_NUMBER9_9FX_771: svga->dac_hwcursor_draw = ibm_rgb528_hwcursor_draw; break; - case S3_SPEA_MERCURY_P64V: - case S3_MIROVIDEO40SV_ERGO_968: - svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; - break; default: + svga->dac_hwcursor_draw = tvp3026_hwcursor_draw; break; } break; @@ -9981,8 +10620,14 @@ s3_init(const device_t *info) s3->width = 1024; svga->ramdac = device_add(&sc11483_ramdac_device); - svga->clock_gen = device_add(&av9194_device); - svga->getclock = av9194_getclock; + if (s3->card_type == S3_ORCHID_86C911) { + svga->clock_gen = device_add(&av9194_device); + svga->getclock = av9194_getclock; + } else { + /* DCS2824-0 = Diamond ICD2061A-compatible. */ + svga->clock_gen = device_add(&icd2061_device); + svga->getclock = icd2061_getclock; + } break; case S3_AMI_86C924: @@ -10092,6 +10737,7 @@ s3_init(const device_t *info) stepping = 0xc0; /*Vision864*/ else stepping = 0xc1; /*Vision864P*/ + s3->id = stepping; s3->id_ext = s3->id_ext_pci = stepping; s3->packed_mmio = 0; @@ -10125,6 +10771,7 @@ s3_init(const device_t *info) } break; + case S3_DIAMOND_STEALTH64_968: case S3_ELSAWIN2KPROX: case S3_SPEA_MERCURY_P64V: case S3_MIROVIDEO40SV_ERGO_968: @@ -10132,8 +10779,9 @@ s3_init(const device_t *info) case S3_PHOENIX_VISION968: svga->decode_mask = (8 << 20) - 1; s3->id = 0xe1; /*Vision968*/ - s3->id_ext = s3->id_ext_pci = 0xf0; - s3->packed_mmio = 1; + s3->id_ext = 0xf0; + s3->id_ext_pci = s3->id_ext; + s3->packed_mmio = 1; if (s3->pci) { svga->crtc[0x53] = 0x18; svga->crtc[0x58] = 0x10; @@ -10147,6 +10795,7 @@ s3_init(const device_t *info) } switch (info->local) { + case S3_DIAMOND_STEALTH64_968: case S3_ELSAWIN2KPROX: case S3_PHOENIX_VISION968: case S3_NUMBER9_9FX_771: @@ -10214,10 +10863,6 @@ s3_init(const device_t *info) case S3_CARDEX_TRIO64VPLUS: case S3_DIAMOND_STEALTH64_764: case S3_SPEA_MIRAGE_P64: - if (device_get_config_int("memory") == 1) - svga->vram_max = 1 << 20; /* Phoenix BIOS does not expect VRAM to be mirrored. */ - /* Fall over. */ - fallthrough; case S3_NUMBER9_9FX: svga->decode_mask = (4 << 20) - 1; s3->id = 0xe1; /*Trio64*/ @@ -10271,6 +10916,8 @@ s3_init(const device_t *info) s3->fifo_thread_run = 1; s3->fifo_thread = thread_create(fifo_thread, s3); + *reset_state = *s3; + return s3; } @@ -10376,6 +11023,12 @@ s3_diamond_stealth64_964_available(void) return rom_present(ROM_DIAMOND_STEALTH64_964); } +static int +s3_diamond_stealth64_968_available(void) +{ + return rom_present(ROM_DIAMOND_STEALTH64_968); +} + static int s3_mirovideo_40sv_ergo_968_pci_available(void) { @@ -10494,6 +11147,9 @@ s3_close(void *priv) ddc_close(s3->ddc); i2c_gpio_close(s3->i2c); + free(reset_state); + reset_state = NULL; + free(s3); } @@ -10593,6 +11249,20 @@ static const device_config_t s3_968_config[] = { { .type = CONFIG_END } }; +static const device_config_t s3_standard_config2[] = { + { .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 4, + .selection = { + { .description = "2 MB", + .value = 2 }, + { .description = "4 MB", + .value = 4 }, + { .description = "" } } }, + { .type = CONFIG_END } +}; + const device_t s3_orchid_86c911_isa_device = { .name = "S3 86c911 ISA (Orchid Fahrenheit 1280)", .internal_name = "orchid_s3_911", @@ -10873,6 +11543,34 @@ const device_t s3_diamond_stealth64_964_pci_device = { .config = s3_standard_config }; +const device_t s3_diamond_stealth64_968_vlb_device = { + .name = "S3 Vision968 VLB (Diamond Stealth64 Video VRAM)", + .internal_name = "stealth64vv_vlb", + .flags = DEVICE_VLB, + .local = S3_DIAMOND_STEALTH64_968, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth64_968_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config2 +}; + +const device_t s3_diamond_stealth64_968_pci_device = { + .name = "S3 Vision968 PCI (Diamond Stealth64 Video VRAM)", + .internal_name = "stealth64vv_pci", + .flags = DEVICE_PCI, + .local = S3_DIAMOND_STEALTH64_968, + .init = s3_init, + .close = s3_close, + .reset = s3_reset, + { .available = s3_diamond_stealth64_968_available }, + .speed_changed = s3_speed_changed, + .force_redraw = s3_force_redraw, + .config = s3_standard_config2 +}; + const device_t s3_9fx_771_pci_device = { .name = "S3 Vision968 PCI (Number 9 9FX 771)", .internal_name = "n9_9fx_771_pci", @@ -10901,20 +11599,6 @@ const device_t s3_phoenix_vision968_pci_device = { .config = s3_standard_config }; -const device_t s3_phoenix_vision968_vlb_device = { - .name = "S3 Vision968 VLB (Phoenix)", - .internal_name = "px_vision968_vlb", - .flags = DEVICE_VLB, - .local = S3_PHOENIX_VISION968, - .init = s3_init, - .close = s3_close, - .reset = s3_reset, - { .available = s3_phoenix_vision968_available }, - .speed_changed = s3_speed_changed, - .force_redraw = s3_force_redraw, - .config = s3_standard_config -}; - const device_t s3_mirovideo_40sv_ergo_968_pci_device = { .name = "S3 Vision968 PCI (MiroVIDEO 40SV Ergo)", .internal_name = "mirovideo40sv_pci", @@ -11195,20 +11879,6 @@ const device_t s3_9fx_531_pci_device = { .config = s3_9fx_config }; -const device_t s3_phoenix_vision868_vlb_device = { - .name = "S3 Vision868 VLB (Phoenix)", - .internal_name = "px_vision868_vlb", - .flags = DEVICE_VLB, - .local = S3_PHOENIX_VISION868, - .init = s3_init, - .close = s3_close, - .reset = s3_reset, - { .available = s3_phoenix_vision868_available }, - .speed_changed = s3_speed_changed, - .force_redraw = s3_force_redraw, - .config = s3_standard_config -}; - const device_t s3_phoenix_vision868_pci_device = { .name = "S3 Vision868 PCI (Phoenix)", .internal_name = "px_vision868_pci", diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 4d64dffbd4..fea5388646 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -40,45 +40,59 @@ #include <86box/vid_svga.h> #include <86box/vid_svga_render.h> -static int dither[4][4] = { - {0, 4, 1, 5}, - { 6, 2, 7, 3}, - { 1, 5, 0, 4}, - { 7, 3, 6, 2}, -}; - -#define RB_SIZE 256 -#define RB_MASK (RB_SIZE - 1) - -#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) -#define RB_FULL (RB_ENTRIES == RB_SIZE) -#define RB_EMPTY (!RB_ENTRIES) - -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) +#ifdef MIN + #undef MIN +#endif +#ifdef MAX + #undef MAX +#endif +#ifdef CLAMP + #undef CLAMP +#endif -#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) -#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= (FIFO_SIZE - 4)) -#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) +static uint64_t virge_time = 0; -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff +static int dither[4][4] = { + {0, 4, 1, 5}, + {6, 2, 7, 3}, + {1, 5, 0, 4}, + {7, 3, 6, 2} +}; #define ROM_VIRGE_325 "roms/video/s3virge/86c325.bin" #define ROM_DIAMOND_STEALTH3D_2000 "roms/video/s3virge/s3virge.bin" +#define ROM_MIROCRYSTAL_3D "roms/video/s3virge/miro Crystal 3D 1.02.bin" #define ROM_DIAMOND_STEALTH3D_3000 "roms/video/s3virge/diamondstealth3000.vbi" #define ROM_STB_VELOCITY_3D "roms/video/s3virge/stb_velocity3d_110.BIN" #define ROM_VIRGE_DX "roms/video/s3virge/86c375_1.bin" #define ROM_DIAMOND_STEALTH3D_2000PRO "roms/video/s3virge/virgedxdiamond.vbi" #define ROM_VIRGE_GX "roms/video/s3virge/86c375_4.bin" #define ROM_VIRGE_GX2 "roms/video/s3virge/flagpoint.VBI" -#define ROM_DIAMOND_STEALTH3D_4000 "roms/video/s3virge/86c357.bin" +#define ROM_DIAMOND_STEALTH3D_4000 "roms/video/s3virge/DS3D4K v1.03 Brightness bug fix.bin" #define ROM_TRIO3D2X "roms/video/s3virge/TRIO3D2X_8mbsdr.VBI" +#define RB_SIZE 256 +#define RB_MASK (RB_SIZE - 1) + +#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx) +#define RB_FULL (RB_ENTRIES == RB_SIZE) +#define RB_EMPTY (!RB_ENTRIES) + +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) + +#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx) +#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= FIFO_SIZE) +#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx) + +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + enum { S3_VIRGE_325, S3_DIAMOND_STEALTH3D_2000, + S3_MIROCRYSTAL_3D, S3_DIAMOND_STEALTH3D_3000, S3_STB_VELOCITY_3D, S3_VIRGE_DX, @@ -98,58 +112,80 @@ enum { }; enum { - FIFO_INVALID = (0x00 << 24), - FIFO_WRITE_BYTE = (0x01 << 24), - FIFO_WRITE_WORD = (0x02 << 24), + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_BYTE = (0x01 << 24), + FIFO_WRITE_WORD = (0x02 << 24), FIFO_WRITE_DWORD = (0x03 << 24) }; -typedef struct -{ - uint32_t addr_type; - uint32_t val; +typedef struct { + uint32_t addr_type; + uint32_t val; } fifo_entry_t; typedef struct s3d_t { - uint32_t cmd_set; - int clip_l, clip_r, clip_t, clip_b; - - uint32_t dest_base; - uint32_t dest_str; - - uint32_t z_base; - uint32_t z_str; - - uint32_t tex_base; - uint32_t tex_bdr_clr; - uint32_t tbv, tbu; - int32_t TdVdX, TdUdX; - int32_t TdVdY, TdUdY; - uint32_t tus, tvs; - - int32_t TdZdX, TdZdY; - uint32_t tzs; - - int32_t TdWdX, TdWdY; - uint32_t tws; - - int32_t TdDdX, TdDdY; - uint32_t tds; - - int16_t TdGdX, TdBdX, TdRdX, TdAdX; - int16_t TdGdY, TdBdY, TdRdY, TdAdY; - uint32_t tgs, tbs, trs, tas; - - uint32_t TdXdY12; - uint32_t txend12; - uint32_t TdXdY01; - uint32_t txend01; - uint32_t TdXdY02; - uint32_t txs; - uint32_t tys; - int ty01, ty12, tlr; - - uint8_t fog_r, fog_g, fog_b; + uint32_t cmd_set; + int clip_l; + int clip_r; + int clip_t; + int clip_b; + + uint32_t dest_base; + uint32_t dest_str; + + uint32_t z_base; + uint32_t z_str; + + uint32_t tex_base; + uint32_t tex_bdr_clr; + uint32_t tbv; + uint32_t tbu; + int32_t TdVdX; + int32_t TdUdX; + int32_t TdVdY; + int32_t TdUdY; + uint32_t tus; + uint32_t tvs; + + int32_t TdZdX; + int32_t TdZdY; + uint32_t tzs; + + int32_t TdWdX; + int32_t TdWdY; + uint32_t tws; + + int32_t TdDdX; + int32_t TdDdY; + uint32_t tds; + + int16_t TdGdX; + int16_t TdBdX; + int16_t TdRdX; + int16_t TdAdX; + int16_t TdGdY; + int16_t TdBdY; + int16_t TdRdY; + int16_t TdAdY; + uint32_t tgs; + uint32_t tbs; + uint32_t trs; + uint32_t tas; + + uint32_t TdXdY12; + uint32_t txend12; + uint32_t TdXdY01; + uint32_t txend01; + uint32_t TdXdY02; + uint32_t txs; + uint32_t tys; + int ty01; + int ty12; + int tlr; + + uint8_t fog_r; + uint8_t fog_g; + uint8_t fog_b; } s3d_t; typedef struct virge_t { @@ -157,48 +193,51 @@ typedef struct virge_t { mem_mapping_t mmio_mapping; mem_mapping_t new_mmio_mapping; - rom_t bios_rom; + rom_t bios_rom; - svga_t svga; + svga_t svga; - uint8_t bank; - uint8_t ma_ext; - uint8_t reg6b, lfb_bios; + uint8_t bank; + uint8_t ma_ext; - uint8_t virge_id, virge_id_high, virge_id_low, virge_rev; + uint8_t virge_id; + uint8_t virge_id_high; + uint8_t virge_id_low; + uint8_t virge_rev; - uint8_t int_line; + uint32_t linear_base; + uint32_t linear_size; - uint32_t linear_base, linear_size; + uint8_t pci_regs[256]; + uint8_t pci_slot; - uint8_t pci_regs[256]; + int chip; - uint8_t pci_slot; - uint8_t irq_state; + int bilinear_enabled; + int dithering_enabled; + int memory_size; - int pci; - int chip; - int is_agp; + int pixel_count; + int tri_count; - int bilinear_enabled; - int dithering_enabled; - uint32_t memory_size; - uint32_t vram_mask; + thread_t * render_thread; + event_t * wake_render_thread; + event_t * wake_main_thread; + event_t * not_full_event; - thread_t *render_thread; - event_t *wake_render_thread; - event_t *wake_main_thread; - event_t *not_full_event; + uint32_t hwc_fg_col; + uint32_t hwc_bg_col; + int hwc_col_stack_pos; - uint32_t hwc_fg_col, hwc_bg_col; - int hwc_col_stack_pos; - - struct - { + struct { uint32_t src_base; uint32_t dest_base; - int clip_l, clip_r, clip_t, clip_b; - int dest_str, src_str; + int clip_l; + int clip_r; + int clip_t; + int clip_b; + int dest_str; + int src_str; uint32_t mono_pat_0; uint32_t mono_pat_1; uint32_t pat_bg_clr; @@ -206,20 +245,28 @@ typedef struct virge_t { uint32_t src_bg_clr; uint32_t src_fg_clr; uint32_t cmd_set; - int r_width, r_height; - int rsrc_x, rsrc_y; - int rdest_x, rdest_y; - - int lxend0, lxend1; + int r_width; + int r_height; + int rsrc_x; + int rsrc_y; + int rdest_x; + int rdest_y; + + int lxend0; + int lxend1; int32_t ldx; - uint32_t lxstart, lystart; + uint32_t lxstart; + uint32_t lystart; int lycnt; int line_dir; - int src_x, src_y; - int dest_x, dest_y; - int w, h; - uint8_t rop; + int src_x; + int src_y; + int dest_x; + int dest_y; + int w; + int h; + uint8_t rop; int data_left_count; uint32_t data_left; @@ -238,14 +285,14 @@ typedef struct virge_t { uint32_t dest_l, dest_r; } s3d; - s3d_t s3d_tri; + s3d_t s3d_tri; - s3d_t s3d_buffer[RB_SIZE]; - atomic_int s3d_read_idx, s3d_write_idx; - atomic_int s3d_busy; + s3d_t s3d_buffer[RB_SIZE]; + atomic_int s3d_read_idx; + atomic_int s3d_write_idx; + atomic_int s3d_busy; - struct - { + struct { uint32_t pri_ctrl; uint32_t chroma_ctrl; uint32_t sec_ctrl; @@ -270,77 +317,120 @@ typedef struct virge_t { uint32_t sec_start; uint32_t sec_size; - int sdif; + int sdif; - int pri_x, pri_y, pri_w, pri_h; - int sec_x, sec_y, sec_w, sec_h; + int pri_x; + int pri_y; + int pri_w; + int pri_h; + int sec_x; + int sec_y; + int sec_w; + int sec_h; } streams; - uint8_t cmd_dma; - uint32_t cmd_dma_base; - uint32_t dma_ptr; - uint64_t blitter_time; - int fifo_slots_num; + fifo_entry_t fifo[FIFO_SIZE]; + atomic_int fifo_read_idx, fifo_write_idx; + atomic_int fifo_thread_run, render_thread_run; + + thread_t * fifo_thread; + event_t *wake_fifo_thread; + event_t * fifo_not_full_event; + + atomic_int virge_busy; - pc_timer_t tri_timer; + uint8_t subsys_stat; + uint8_t subsys_cntl; - int virge_busy, local; + int local; - uint8_t subsys_stat, subsys_cntl, advfunc_cntl; + uint8_t serialport; - uint8_t render_thread_run; + uint8_t irq_state; + uint8_t advfunc_cntl; - uint8_t serialport; + void *i2c, *ddc; - void *i2c, *ddc; + int onboard; + int fifo_slots_num; + + uint32_t vram_mask; + + uint8_t reg6b; + uint8_t lfb_bios; + uint8_t int_line; + uint8_t cmd_dma; - int waiting; + uint32_t cmd_dma_base; + uint32_t cmd_dma_buf_size; + uint32_t cmd_dma_buf_size_mask; + uint32_t cmd_base_addr; + uint32_t cmd_dma_write_ptr_reg; + uint32_t cmd_dma_write_ptr_update; + uint32_t cmd_dma_read_ptr_reg; + uint32_t dma_val; + uint32_t dma_dbl_words; + uint32_t dma_mmio_addr; + uint32_t dma_data_type; + + int pci; + int is_agp; } virge_t; +static __inline void +wake_fifo_thread(virge_t *virge) { + /* Wake up FIFO thread if moving from idle */ + thread_set_event(virge->wake_fifo_thread); +} + +static virge_t *reset_state = NULL; + static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; static video_timings_t timing_diamond_stealth3d_3000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 4, .read_b = 26, .read_w = 26, .read_l = 42 }; static video_timings_t timing_virge_dx_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; static video_timings_t timing_virge_agp = { .type = VIDEO_AGP, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 }; -static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri); +static void queue_triangle(virge_t *virge); -static void s3_virge_recalctimings(svga_t *svga); -static void s3_virge_updatemapping(virge_t *virge); +static void s3_virge_recalctimings(svga_t *svga); +static void s3_virge_updatemapping(virge_t *virge); -static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); +static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat); static uint8_t s3_virge_mmio_read(uint32_t addr, void *priv); -static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *rivp); +static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *priv); static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *priv); static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv); static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv); static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv); +static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type); + enum { - CMD_SET_AE = 1, - CMD_SET_HC = (1 << 1), + CMD_SET_AE = 1, + CMD_SET_HC = (1 << 1), - CMD_SET_FORMAT_MASK = (7 << 2), - CMD_SET_FORMAT_8 = (0 << 2), - CMD_SET_FORMAT_16 = (1 << 2), - CMD_SET_FORMAT_24 = (2 << 2), + CMD_SET_FORMAT_MASK = (7 << 2), + CMD_SET_FORMAT_8 = (0 << 2), + CMD_SET_FORMAT_16 = (1 << 2), + CMD_SET_FORMAT_24 = (2 << 2), - CMD_SET_MS = (1 << 6), - CMD_SET_IDS = (1 << 7), - CMD_SET_MP = (1 << 8), - CMD_SET_TP = (1 << 9), + CMD_SET_MS = (1 << 6), + CMD_SET_IDS = (1 << 7), + CMD_SET_MP = (1 << 8), + CMD_SET_TP = (1 << 9), - CMD_SET_ITA_MASK = (3 << 10), - CMD_SET_ITA_BYTE = (0 << 10), - CMD_SET_ITA_WORD = (1 << 10), - CMD_SET_ITA_DWORD = (2 << 10), + CMD_SET_ITA_MASK = (3 << 10), + CMD_SET_ITA_BYTE = (0 << 10), + CMD_SET_ITA_WORD = (1 << 10), + CMD_SET_ITA_DWORD = (2 << 10), - CMD_SET_ZUP = (1 << 23), + CMD_SET_ZUP = (1 << 23), - CMD_SET_ZB_MODE = (3 << 24), + CMD_SET_ZB_MODE = (3 << 24), - CMD_SET_XP = (1 << 25), - CMD_SET_YP = (1 << 26), + CMD_SET_XP = (1 << 25), + CMD_SET_YP = (1 << 26), CMD_SET_COMMAND_MASK = (15 << 27) }; @@ -351,17 +441,19 @@ enum { #define CMD_SET_TWE (1 << 26) enum { - CMD_SET_COMMAND_BITBLT = (0 << 27), - CMD_SET_COMMAND_RECTFILL = (2 << 27), - CMD_SET_COMMAND_LINE = (3 << 27), - CMD_SET_COMMAND_POLY = (5 << 27), - CMD_SET_COMMAND_NOP = (15 << 27) + CMD_SET_COMMAND_BITBLT = (0 << 27), + CMD_SET_COMMAND_RECTFILL = (2 << 27), + CMD_SET_COMMAND_LINE = (3 << 27), + CMD_SET_COMMAND_POLY = (5 << 27), + CMD_SET_COMMAND_NOP = (15 << 27) }; #define INT_VSY (1 << 0) #define INT_S3D_DONE (1 << 1) #define INT_FIFO_OVF (1 << 2) #define INT_FIFO_EMP (1 << 3) +#define INT_HOST_DONE (1 << 4) +#define INT_CMD_DONE (1 << 5) #define INT_3DF_EMP (1 << 6) #define INT_MASK 0xff @@ -370,89 +462,19 @@ enum { #define SERIAL_PORT_SCR (1 << 2) #define SERIAL_PORT_SDR (1 << 3) -#ifdef ENABLE_S3_VIRGE_LOG -int s3_virge_do_log = ENABLE_S3_VIRGE_LOG; - -static void -s3_virge_log(const char *fmt, ...) -{ - va_list ap; - - if (s3_virge_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define s3_virge_log(fmt, ...) -#endif - -static void -s3_virge_tri_timer(void *priv) -{ - virge_t *virge = (virge_t *) priv; - - thread_set_event(virge->wake_render_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void -queue_triangle(virge_t *virge) -{ - if (RB_FULL) { - thread_reset_event(virge->not_full_event); - thread_reset_event(virge->wake_main_thread); - if (RB_FULL) { - thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ - thread_wait_event(virge->wake_main_thread, -1); - } - } - virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; - virge->s3d_write_idx++; - - if (!virge->s3d_busy) { - if (!(timer_is_enabled(&virge->tri_timer))) - timer_set_delay_u64(&virge->tri_timer, 100 * TIMER_USEC); - } -} - static void -s3_virge_update_irqs(virge_t *virge) -{ - if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & (virge->subsys_cntl & INT_MASK))) +s3_virge_update_irqs(virge_t *virge) { + if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK)) pci_set_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); else pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state); } -static void -render_thread(void *param) -{ - virge_t *virge = (virge_t *) param; - - while (virge->render_thread_run) { - thread_wait_event(virge->wake_render_thread, -1); - thread_reset_event(virge->wake_render_thread); - virge->s3d_busy = 1; - while (!RB_EMPTY) { - s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); - virge->s3d_read_idx++; - if (RB_ENTRIES == RB_MASK) { - thread_set_event(virge->not_full_event); - thread_set_event(virge->wake_main_thread); - } - } - virge->s3d_busy = 0; - virge->subsys_stat |= INT_S3D_DONE; - s3_virge_update_irqs(virge); - } -} - static void s3_virge_out(uint16_t addr, uint8_t val, void *priv) { virge_t *virge = (virge_t *) priv; - svga_t *svga = &virge->svga; + svga_t * svga = &virge->svga; uint8_t old; uint32_t cursoraddr; @@ -462,12 +484,11 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) switch (addr) { case 0x3c5: if (svga->seqaddr >= 0x10) { - svga->seqregs[svga->seqaddr & 0x1f] = val; + svga->seqregs[svga->seqaddr] = val; svga_recalctimings(svga); return; } - if (svga->seqaddr == 4) /*Chain-4 - update banking*/ - { + if (svga->seqaddr == 4) { /*Chain-4 - update banking*/ if (val & 8) svga->write_bank = svga->read_bank = virge->bank << 16; else @@ -491,19 +512,17 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) + if ((svga->crtcreg >= 0x20) && (svga->crtcreg < 0x40) && + (svga->crtcreg != 0x36) && (svga->crtcreg != 0x38) && + (svga->crtcreg != 0x39) && ((svga->crtc[0x38] & 0xcc) != 0x48)) return; if ((svga->crtcreg >= 0x40) && ((svga->crtc[0x39] & 0xe0) != 0xa0)) return; if ((svga->crtcreg == 0x36) && (svga->crtc[0x39] != 0xa5)) return; - if (svga->crtcreg >= 0x80) - return; - old = svga->crtc[svga->crtcreg]; - svga->crtc[svga->crtcreg] = val; - if (svga->crtcreg > 0x18) - s3_virge_log("OUTB VGA reg = %02x, val = %02x\n", svga->crtcreg, val); + old = svga->crtc[svga->crtcreg]; + svga->crtc[svga->crtcreg] = val; switch (svga->crtcreg) { case 0x31: @@ -561,7 +580,8 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.xoff = svga->crtc[0x4e] & 0x3f; svga->hwcursor.yoff = svga->crtc[0x4f] & 0x3f; cursoraddr = (virge->memory_size == 8) ? 0x1fff : 0x0fff; - svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & cursoraddr) * 1024) + (svga->hwcursor.yoff * 16); + svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | + svga->crtc[0x4d]) & cursoraddr) * 1024) + (svga->hwcursor.yoff * 16); break; case 0x4a: @@ -585,7 +605,7 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) switch (virge->hwc_col_stack_pos) { case 0: virge->hwc_bg_col = (virge->hwc_bg_col & 0xffff00) | val; - break; + break; case 1: virge->hwc_bg_col = (virge->hwc_bg_col & 0xff00ff) | (val << 8); break; @@ -633,8 +653,8 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) svga->bpp = (virge->chip == S3_VIRGEVX) ? 24 : 32; break; default: - svga->bpp = 8; - break; + svga->bpp = 8; + break; } break; @@ -649,7 +669,8 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) { if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) { svga->fullchange = 3; - svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5); + svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + + ((svga->crtc[8] & 0x60) >> 5); if ((svga->crtc[0x67] & 0xc) != 0xc) svga->ma_latch |= (virge->ma_ext << 16); } else { @@ -667,10 +688,9 @@ s3_virge_out(uint16_t addr, uint8_t val, void *priv) } static uint8_t -s3_virge_in(uint16_t addr, void *priv) -{ +s3_virge_in(uint16_t addr, void *priv) { virge_t *virge = (virge_t *) priv; - svga_t *svga = &virge->svga; + svga_t * svga = &virge->svga; uint8_t ret; if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) @@ -686,17 +706,17 @@ s3_virge_in(uint16_t addr, void *priv) case 0x3c5: if (svga->seqaddr >= 8) - ret = svga->seqregs[svga->seqaddr & 0x1f]; + ret = svga->seqregs[svga->seqaddr]; else if (svga->seqaddr <= 4) ret = svga_in(addr, svga); else ret = 0xff; break; - case 0x3D4: + case 0x3d4: ret = svga->crtcreg; break; - case 0x3D5: + case 0x3d5: switch (svga->crtcreg) { case 0x2d: ret = virge->virge_id_high; @@ -721,7 +741,7 @@ s3_virge_in(uint16_t addr, void *priv) break; case 0x45: virge->hwc_col_stack_pos = 0; - ret = svga->crtc[0x45]; + ret = svga->crtc[0x45]; break; case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); @@ -768,13 +788,14 @@ s3_virge_in(uint16_t addr, void *priv) ret = svga_in(addr, svga); break; } + return ret; } static void s3_virge_recalctimings(svga_t *svga) { - const virge_t *virge = (virge_t *) svga->priv; + virge_t *virge = (virge_t *) svga->priv; svga->hdisp = svga->hdisp_old; @@ -790,28 +811,28 @@ s3_virge_recalctimings(svga_t *svga) } if (svga->crtc[0x5d] & 0x01) - svga->htotal += 0x100; + svga->htotal |= 0x100; if (svga->crtc[0x5d] & 0x02) { - svga->hdisp_time += 0x100; - svga->hdisp += 0x100 * svga->dots_per_clock; + svga->hdisp_time |= 0x100; + svga->hdisp |= (0x100 * svga->dots_per_clock); } if (svga->crtc[0x5e] & 0x01) - svga->vtotal += 0x400; + svga->vtotal |= 0x400; if (svga->crtc[0x5e] & 0x02) - svga->dispend += 0x400; + svga->dispend |= 0x400; if (svga->crtc[0x5e] & 0x04) - svga->vblankstart += 0x400; + svga->vblankstart |= 0x400; if (svga->crtc[0x5e] & 0x10) - svga->vsyncstart += 0x400; + svga->vsyncstart |= 0x400; if (svga->crtc[0x5e] & 0x40) - svga->split += 0x400; + svga->split |= 0x400; svga->interlace = svga->crtc[0x42] & 0x20; if (((svga->miscout >> 2) & 3) == 3) { int n = svga->seqregs[0x12] & 0x1f; int r = (svga->seqregs[0x12] >> 5); - if (virge->chip == S3_VIRGEVX || virge->chip == S3_VIRGEDX) + if ((virge->chip == S3_VIRGEVX) || (virge->chip == S3_VIRGEDX)) r &= 7; else if (virge->chip >= S3_VIRGEGX2) r &= 10; @@ -845,88 +866,75 @@ s3_virge_recalctimings(svga_t *svga) video_force_resize_set_monitor(1, svga->monitor_index); } - /* ViRGE/GX2 and later does not use primary stream registers. */ - if ((svga->crtc[0x67] & 0xc) != 0xc || virge->chip >= S3_VIRGEGX2) /*VGA mode*/ - { + if ((svga->crtc[0x67] & 0xc) != 0xc) { /*VGA mode*/ svga->ma_latch |= (virge->ma_ext << 16); if (svga->crtc[0x51] & 0x30) - svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4; + svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; else if (svga->crtc[0x43] & 0x04) - svga->rowoffset += 0x100; + svga->rowoffset |= 0x100; if (!svga->rowoffset) svga->rowoffset = 256; svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)); - if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) { - switch (svga->bpp) { - case 8: - svga->render = svga_render_8bpp_highres; - break; - case 15: - svga->render = svga_render_15bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { - // svga->htotal >>= 1; - // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) - // svga->hblank_end_val = svga->htotal - 1; - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; - case 16: - svga->render = svga_render_16bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) { - // svga->htotal >>= 1; - // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) - // svga->hblank_end_val = svga->htotal - 1; - svga->hdisp >>= 1; - svga->dots_per_clock >>= 1; - } - break; - case 24: - svga->render = svga_render_24bpp_highres; - if (virge->chip != S3_VIRGEVX && virge->chip < S3_VIRGEGX2) - svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/ - break; - case 32: - svga->render = svga_render_32bpp_highres; - break; + if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } + break; + case 16: + svga->render = svga_render_16bpp_highres; + if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) { + svga->hdisp >>= 1; + svga->dots_per_clock >>= 1; + } + break; + case 24: + svga->render = svga_render_24bpp_highres; + if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2)) + svga->rowoffset = (svga->rowoffset * 3) >> 2; /*Hack*/ + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; - default: - break; - } + default: + break; } - svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; - svga->overlay.ena = 0; - s3_virge_log("VGA mode\n"); - if (virge->chip >= S3_VIRGEGX2 && (svga->crtc[0x67] & 0xc) == 0xc) { - /* ViRGE/GX2 and later does not use primary stream registers. */ - svga->overlay.x = virge->streams.sec_x; - svga->overlay.y = virge->streams.sec_y; - svga->overlay.cur_ysize = virge->streams.sec_h; - - if (virge->streams.buffer_ctrl & 2) - svga->overlay.addr = virge->streams.sec_fb1; + + svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && + (svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask; + } else { /*Streams mode*/ + if (virge->chip < S3_VIRGEGX2) { + if (virge->streams.buffer_ctrl & 1) + svga->ma_latch = virge->streams.pri_fb1 >> 2; else - svga->overlay.addr = virge->streams.sec_fb0; + svga->ma_latch = virge->streams.pri_fb0 >> 2; - svga->overlay.ena = (svga->overlay.x >= 0) && !!(virge->streams.blend_ctrl & 0x20); - svga->overlay.v_acc = virge->streams.dda_vert_accumulator; - svga->rowoffset = virge->streams.pri_stride >> 3; - svga->vram_display_mask = virge->vram_mask; - } - } else /*Streams mode*/ - { - if (virge->streams.buffer_ctrl & 1) - svga->ma_latch = virge->streams.pri_fb1 >> 2; - else - svga->ma_latch = virge->streams.pri_fb0 >> 2; + svga->hdisp = virge->streams.pri_w + 1; + if (virge->streams.pri_h < svga->dispend) + svga->dispend = virge->streams.pri_h; - svga->hdisp = virge->streams.pri_w + 1; - if (virge->streams.pri_h < svga->dispend) - svga->dispend = virge->streams.pri_h; + svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; + svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; + } else { + svga->ma_latch |= (virge->ma_ext << 16); + if (svga->crtc[0x51] & 0x30) + svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4; + else if (svga->crtc[0x43] & 0x04) + svga->rowoffset |= 0x100; + if (!svga->rowoffset) + svga->rowoffset = 256; + + svga->overlay.x = virge->streams.sec_x; + svga->overlay.y = virge->streams.sec_y; + } - svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x; - svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y; svga->overlay.cur_ysize = virge->streams.sec_h; if (virge->streams.buffer_ctrl & 2) @@ -934,78 +942,75 @@ s3_virge_recalctimings(svga_t *svga) else svga->overlay.addr = virge->streams.sec_fb0; - svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.ena = (svga->overlay.x >= 0); + svga->overlay.h_acc = virge->streams.dda_horiz_accumulator; svga->overlay.v_acc = virge->streams.dda_vert_accumulator; - svga->rowoffset = virge->streams.pri_stride >> 3; + + if (virge->chip < S3_VIRGEGX2) + svga->rowoffset = virge->streams.pri_stride >> 3; if (virge->chip <= S3_VIRGEDX && svga->overlay.ena) { - svga->overlay.ena = (((virge->streams.blend_ctrl >> 24) & 7) == 0b000) || (((virge->streams.blend_ctrl >> 24) & 7) == 0b101); - } else if (virge->chip == S3_VIRGEGX2 && svga->overlay.ena) { + svga->overlay.ena = (((virge->streams.blend_ctrl >> 24) & 7) == 0b000) || + (((virge->streams.blend_ctrl >> 24) & 7) == 0b101); + } else if (virge->chip >= S3_VIRGEGX2 && svga->overlay.ena) { /* 0x20 = Secondary Stream enabled */ /* 0x2000 = Primary Stream enabled */ svga->overlay.ena = !!(virge->streams.blend_ctrl & 0x20); } - switch ((virge->streams.pri_ctrl >> 24) & 0x7) { - case 0: /*RGB-8 (CLUT)*/ - svga->render = svga_render_8bpp_highres; - break; - case 3: /*KRGB-16 (1.5.5.5)*/ - // svga->htotal >>= 1; - // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) - // svga->hblank_end_val = svga->htotal - 1; - // svga->dots_per_clock >>= 1; - svga->render = svga_render_15bpp_highres; - break; - case 5: /*RGB-16 (5.6.5)*/ - // svga->htotal >>= 1; - // if ((svga->crtc[0x33] & 0x20) || ((svga->crtc[0x67] & 0xc) == 0xc)) - // svga->hblank_end_val = svga->htotal - 1; - // svga->dots_per_clock >>= 1; - svga->render = svga_render_16bpp_highres; - break; - case 6: /*RGB-24 (8.8.8)*/ - svga->render = svga_render_24bpp_highres; - break; - case 7: /*XRGB-32 (X.8.8.8)*/ - svga->render = svga_render_32bpp_highres; - break; + if (virge->chip >= S3_VIRGEGX2) { + switch (svga->bpp) { + case 8: + svga->render = svga_render_8bpp_highres; + break; + case 15: + svga->render = svga_render_15bpp_highres; + break; + case 16: + svga->render = svga_render_16bpp_highres; + break; + case 24: + svga->render = svga_render_24bpp_highres; + break; + case 32: + svga->render = svga_render_32bpp_highres; + break; - default: - break; + default: + break; + } + } else { + switch ((virge->streams.pri_ctrl >> 24) & 0x7) { + case 0: /*RGB-8 (CLUT)*/ + svga->render = svga_render_8bpp_highres; + break; + case 3: /*KRGB-16 (1.5.5.5)*/ + svga->render = svga_render_15bpp_highres; + break; + case 5: /*RGB-16 (5.6.5)*/ + svga->render = svga_render_16bpp_highres; + break; + case 6: /*RGB-24 (8.8.8)*/ + svga->render = svga_render_24bpp_highres; + break; + case 7: /*XRGB-32 (X.8.8.8)*/ + svga->render = svga_render_32bpp_highres; + break; + } } svga->vram_display_mask = virge->vram_mask; } svga->hoverride = 1; -} - -static void -s3_virge_update_buffer(virge_t *virge) -{ - svga_t *svga = &virge->svga; - - if ((svga->crtc[0x67] & 0xc) != 0xc) - return; - if (virge->chip < S3_VIRGEGX2) { - if (virge->streams.buffer_ctrl & 1) - svga->ma_latch = virge->streams.pri_fb1 >> 2; - else - svga->ma_latch = virge->streams.pri_fb0 >> 2; - } - - if (virge->streams.buffer_ctrl & 2) - svga->overlay.addr = virge->streams.sec_fb1; - else - svga->overlay.addr = virge->streams.sec_fb0; - - svga->rowoffset = virge->streams.pri_stride >> 3; + if (svga->render == svga_render_2bpp_lowres) + svga->render = svga_render_2bpp_s3_lowres; + else if (svga->render == svga_render_2bpp_highres) + svga->render = svga_render_2bpp_s3_highres; } static void -s3_virge_updatemapping(virge_t *virge) -{ +s3_virge_updatemapping(virge_t *virge) { svga_t *svga = &virge->svga; if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { @@ -1016,10 +1021,8 @@ s3_virge_updatemapping(virge_t *virge) return; } - s3_virge_log("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc); - /*Banked framebuffer*/ - switch (svga->gdcreg[6] & 0xc) { /*VGA mapping*/ - case 0x0: /*128k at A0000*/ + switch (svga->gdcreg[6] & 0xc) { /*Banked framebuffer*/ + case 0x0: /*128k at A0000*/ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); svga->banked_mask = 0xffff; break; @@ -1035,14 +1038,10 @@ s3_virge_updatemapping(virge_t *virge) mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); svga->banked_mask = 0x7fff; break; - - default: - break; } virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24); - s3_virge_log("Linear framebuffer %02X, linear base = %08x, display mask = %08x\n", svga->crtc[0x58] & 0x17, virge->linear_base, svga->vram_display_mask); if ((svga->crtc[0x58] & 0x10) || (virge->advfunc_cntl & 0x10)) { /*Linear framebuffer*/ switch (svga->crtc[0x58] & 7) { case 0: /*64k*/ @@ -1055,7 +1054,7 @@ s3_virge_updatemapping(virge_t *virge) virge->linear_size = 0x200000; break; case 3: /*4mb on other than ViRGE/VX, 8mb on ViRGE/VX*/ - if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) + if ((virge->chip == S3_VIRGEVX) || (virge->chip == S3_TRIO3D2X)) virge->linear_size = 0x800000; else virge->linear_size = 0x400000; @@ -1063,21 +1062,16 @@ s3_virge_updatemapping(virge_t *virge) case 7: virge->linear_size = 0x800000; break; - - default: - break; } virge->linear_base &= ~(virge->linear_size - 1); - s3_virge_log("Linear framebuffer at %08X size %08X, mask = %08x, CRTC58 sel = %02x\n", virge->linear_base, virge->linear_size, virge->vram_mask, svga->crtc[0x58] & 7); if (virge->linear_base == 0xa0000) { mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); mem_mapping_disable(&virge->linear_mapping); } else { - if (virge->chip == S3_VIRGEVX || virge->chip == S3_TRIO3D2X) { + if ((virge->chip == S3_VIRGEVX) || (virge->chip == S3_TRIO3D2X)) virge->linear_base &= 0xfe000000; - } else { + else virge->linear_base &= 0xfc000000; - } mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size); } @@ -1087,11 +1081,7 @@ s3_virge_updatemapping(virge_t *virge) svga->fb_only = 0; } - s3_virge_log("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x38); - - /* Memory mapped I/O. */ - /* Old MMIO. */ - if ((svga->crtc[0x53] & 0x10) || (virge->advfunc_cntl & 0x20)) { + if ((svga->crtc[0x53] & 0x10) || (virge->advfunc_cntl & 0x20)) { /*Old MMIO*/ if (svga->crtc[0x53] & 0x20) mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000); else @@ -1099,16 +1089,14 @@ s3_virge_updatemapping(virge_t *virge) } else mem_mapping_disable(&virge->mmio_mapping); - /* New MMIO. */ - if (svga->crtc[0x53] & 0x08) + if (svga->crtc[0x53] & 0x08) /*New MMIO*/ mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000); else mem_mapping_disable(&virge->new_mmio_mapping); } static void -s3_virge_vblank_start(svga_t *svga) -{ +s3_virge_vblank_start(svga_t *svga) { virge_t *virge = (virge_t *) svga->priv; virge->subsys_stat |= INT_VSY; @@ -1116,483 +1104,10 @@ s3_virge_vblank_start(svga_t *svga) } static void -s3_virge_mmio_fifo_write(uint32_t addr, uint8_t val, virge_t *virge) -{ - if ((addr & 0xffff) < 0x8000) - s3_virge_bitblt(virge, 8, val); - else { - switch (addr & 0xffff) { - case 0x859c: - virge->cmd_dma = val; - break; - - default: - break; - } - } -} - -static void -s3_virge_mmio_fifo_write_w(uint32_t addr, uint16_t val, virge_t *virge) -{ - if ((addr & 0xfffe) < 0x8000) { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); - else - s3_virge_bitblt(virge, 16, val); - } else { - if ((addr & 0xfffe) == 0x859c) - virge->cmd_dma = val; - } -} - -static void -s3_virge_mmio_fifo_write_l(uint32_t addr, uint32_t val, virge_t *virge) -{ - if ((addr & 0xfffc) < 0x8000) { - if (virge->s3d.cmd_set & CMD_SET_MS) - s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); - else - s3_virge_bitblt(virge, 32, val); - } else { - switch (addr & 0xfffc) { - case 0x8590: - virge->cmd_dma_base = val; - break; - - case 0x8594: - virge->dma_ptr = val; - break; - - case 0x8598: - break; - - case 0x859c: - virge->cmd_dma = val; - break; - - case 0xa000: - case 0xa004: - case 0xa008: - case 0xa00c: - case 0xa010: - case 0xa014: - case 0xa018: - case 0xa01c: - case 0xa020: - case 0xa024: - case 0xa028: - case 0xa02c: - case 0xa030: - case 0xa034: - case 0xa038: - case 0xa03c: - case 0xa040: - case 0xa044: - case 0xa048: - case 0xa04c: - case 0xa050: - case 0xa054: - case 0xa058: - case 0xa05c: - case 0xa060: - case 0xa064: - case 0xa068: - case 0xa06c: - case 0xa070: - case 0xa074: - case 0xa078: - case 0xa07c: - case 0xa080: - case 0xa084: - case 0xa088: - case 0xa08c: - case 0xa090: - case 0xa094: - case 0xa098: - case 0xa09c: - case 0xa0a0: - case 0xa0a4: - case 0xa0a8: - case 0xa0ac: - case 0xa0b0: - case 0xa0b4: - case 0xa0b8: - case 0xa0bc: - case 0xa0c0: - case 0xa0c4: - case 0xa0c8: - case 0xa0cc: - case 0xa0d0: - case 0xa0d4: - case 0xa0d8: - case 0xa0dc: - case 0xa0e0: - case 0xa0e4: - case 0xa0e8: - case 0xa0ec: - case 0xa0f0: - case 0xa0f4: - case 0xa0f8: - case 0xa0fc: - case 0xa100: - case 0xa104: - case 0xa108: - case 0xa10c: - case 0xa110: - case 0xa114: - case 0xa118: - case 0xa11c: - case 0xa120: - case 0xa124: - case 0xa128: - case 0xa12c: - case 0xa130: - case 0xa134: - case 0xa138: - case 0xa13c: - case 0xa140: - case 0xa144: - case 0xa148: - case 0xa14c: - case 0xa150: - case 0xa154: - case 0xa158: - case 0xa15c: - case 0xa160: - case 0xa164: - case 0xa168: - case 0xa16c: - case 0xa170: - case 0xa174: - case 0xa178: - case 0xa17c: - case 0xa180: - case 0xa184: - case 0xa188: - case 0xa18c: - case 0xa190: - case 0xa194: - case 0xa198: - case 0xa19c: - case 0xa1a0: - case 0xa1a4: - case 0xa1a8: - case 0xa1ac: - case 0xa1b0: - case 0xa1b4: - case 0xa1b8: - case 0xa1bc: - case 0xa1c0: - case 0xa1c4: - case 0xa1c8: - case 0xa1cc: - case 0xa1d0: - case 0xa1d4: - case 0xa1d8: - case 0xa1dc: - case 0xa1e0: - case 0xa1e4: - case 0xa1e8: - case 0xa1ec: - case 0xa1f0: - case 0xa1f4: - case 0xa1f8: - case 0xa1fc: - { - int x = addr & 4; - int y = (addr >> 3) & 7; - int color; - int byte; - virge->s3d.pattern_8[y * 8 + x] = val & 0xff; - virge->s3d.pattern_8[y * 8 + x + 1] = val >> 8; - virge->s3d.pattern_8[y * 8 + x + 2] = val >> 16; - virge->s3d.pattern_8[y * 8 + x + 3] = val >> 24; - - x = (addr >> 1) & 6; - y = (addr >> 4) & 7; - virge->s3d.pattern_16[y * 8 + x] = val & 0xffff; - virge->s3d.pattern_16[y * 8 + x + 1] = val >> 16; - - addr &= 0x00ff; - for (uint8_t xx = 0; xx < 4; xx++) { - x = ((addr + xx) / 3) % 8; - y = ((addr + xx) / 24) % 8; - color = ((addr + xx) % 3) << 3; - byte = (xx << 3); - virge->s3d.pattern_24[y * 8 + x] &= ~(0xff << color); - virge->s3d.pattern_24[y * 8 + x] |= ((val >> byte) & 0xff) << color; - } - - x = (addr >> 2) & 7; - y = (addr >> 5) & 7; - virge->s3d.pattern_32[y * 8 + x] = val & 0xffffff; - } - break; - - case 0xa4d4: - case 0xa8d4: - virge->s3d.src_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - s3_virge_log("PortWrite = %04x, SRC Base = %08x, memsize = %i\n", addr & 0xfffc, val, virge->memory_size); - break; - case 0xa4d8: - case 0xa8d8: - virge->s3d.dest_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - s3_virge_log("PortWrite = %04x, DST Base = %08x, memsize = %i\n", addr & 0xfffc, val, virge->memory_size); - break; - case 0xa4dc: - case 0xa8dc: - virge->s3d.clip_l = (val >> 16) & 0x7ff; - virge->s3d.clip_r = val & 0x7ff; - break; - case 0xa4e0: - case 0xa8e0: - virge->s3d.clip_t = (val >> 16) & 0x7ff; - virge->s3d.clip_b = val & 0x7ff; - break; - case 0xa4e4: - case 0xa8e4: - virge->s3d.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xa4e8: - case 0xace8: - virge->s3d.mono_pat_0 = val; - break; - case 0xa4ec: - case 0xacec: - virge->s3d.mono_pat_1 = val; - break; - case 0xa4f0: - case 0xacf0: - virge->s3d.pat_bg_clr = val; - break; - case 0xa4f4: - case 0xa8f4: - case 0xacf4: - virge->s3d.pat_fg_clr = val; - break; - case 0xa4f8: - virge->s3d.src_bg_clr = val; - break; - case 0xa4fc: - virge->s3d.src_fg_clr = val; - break; - case 0xa500: - case 0xa900: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) { - s3_virge_bitblt(virge, -1, 0); - } - break; - case 0xa504: - virge->s3d.r_width = (val >> 16) & 0x7ff; - virge->s3d.r_height = val & 0x7ff; - break; - case 0xa508: - virge->s3d.rsrc_x = (val >> 16) & 0x7ff; - virge->s3d.rsrc_y = val & 0x7ff; - break; - case 0xa50c: - virge->s3d.rdest_x = (val >> 16) & 0x7ff; - virge->s3d.rdest_y = val & 0x7ff; - if (virge->s3d.cmd_set & CMD_SET_AE) { - s3_virge_bitblt(virge, -1, 0); - } - break; - case 0xa96c: - virge->s3d.lxend0 = (val >> 16) & 0x7ff; - virge->s3d.lxend1 = val & 0x7ff; - break; - case 0xa970: - virge->s3d.ldx = (int32_t) val; - break; - case 0xa974: - virge->s3d.lxstart = val; - break; - case 0xa978: - virge->s3d.lystart = val & 0x7ff; - break; - case 0xa97c: - virge->s3d.lycnt = val & 0x7ff; - virge->s3d.line_dir = val >> 31; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xad00: - virge->s3d.cmd_set = val; - if (!(val & CMD_SET_AE)) - s3_virge_bitblt(virge, -1, 0); - break; - case 0xad68: - virge->s3d.prdx = val; - break; - case 0xad6c: - virge->s3d.prxstart = val; - break; - case 0xad70: - virge->s3d.pldx = val; - break; - case 0xad74: - virge->s3d.plxstart = val; - break; - case 0xad78: - virge->s3d.pystart = val & 0x7ff; - break; - case 0xad7c: - virge->s3d.pycnt = val & 0x300007ff; - if (virge->s3d.cmd_set & CMD_SET_AE) - s3_virge_bitblt(virge, -1, 0); - break; - - case 0xb0f4: - case 0xb4f4: - virge->s3d_tri.fog_b = val & 0xff; - virge->s3d_tri.fog_g = (val >> 8) & 0xff; - virge->s3d_tri.fog_r = (val >> 16) & 0xff; - break; - case 0xb4d4: - virge->s3d_tri.z_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - break; - case 0xb4d8: - virge->s3d_tri.dest_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - break; - case 0xb4dc: - virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_r = val & 0x7ff; - break; - case 0xb4e0: - virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; - virge->s3d_tri.clip_b = val & 0x7ff; - break; - case 0xb4e4: - virge->s3d_tri.dest_str = (val >> 16) & 0xff8; - virge->s3d.src_str = val & 0xff8; - break; - case 0xb4e8: - virge->s3d_tri.z_str = val & 0xff8; - break; - case 0xb4ec: - virge->s3d_tri.tex_base = (virge->memory_size == 8) ? (val & 0x7ffff8) : (val & 0x3ffff8); - break; - case 0xb4f0: - virge->s3d_tri.tex_bdr_clr = val & 0xffffff; - break; - case 0xb500: - virge->s3d_tri.cmd_set = val; - if (!(val & CMD_SET_AE)) - queue_triangle(virge); - break; - case 0xb504: - virge->s3d_tri.tbv = val & 0xfffff; - break; - case 0xb508: - virge->s3d_tri.tbu = val & 0xfffff; - break; - case 0xb50c: - virge->s3d_tri.TdWdX = val; - break; - case 0xb510: - virge->s3d_tri.TdWdY = val; - break; - case 0xb514: - virge->s3d_tri.tws = val; - break; - case 0xb518: - virge->s3d_tri.TdDdX = val; - break; - case 0xb51c: - virge->s3d_tri.TdVdX = val; - break; - case 0xb520: - virge->s3d_tri.TdUdX = val; - break; - case 0xb524: - virge->s3d_tri.TdDdY = val; - break; - case 0xb528: - virge->s3d_tri.TdVdY = val; - break; - case 0xb52c: - virge->s3d_tri.TdUdY = val; - break; - case 0xb530: - virge->s3d_tri.tds = val; - break; - case 0xb534: - virge->s3d_tri.tvs = val; - break; - case 0xb538: - virge->s3d_tri.tus = val; - break; - case 0xb53c: - virge->s3d_tri.TdGdX = val >> 16; - virge->s3d_tri.TdBdX = val & 0xffff; - break; - case 0xb540: - virge->s3d_tri.TdAdX = val >> 16; - virge->s3d_tri.TdRdX = val & 0xffff; - break; - case 0xb544: - virge->s3d_tri.TdGdY = val >> 16; - virge->s3d_tri.TdBdY = val & 0xffff; - break; - case 0xb548: - virge->s3d_tri.TdAdY = val >> 16; - virge->s3d_tri.TdRdY = val & 0xffff; - break; - case 0xb54c: - virge->s3d_tri.tgs = (val >> 16) & 0xffff; - virge->s3d_tri.tbs = val & 0xffff; - break; - case 0xb550: - virge->s3d_tri.tas = (val >> 16) & 0xffff; - virge->s3d_tri.trs = val & 0xffff; - break; - - case 0xb554: - virge->s3d_tri.TdZdX = val; - break; - case 0xb558: - virge->s3d_tri.TdZdY = val; - break; - case 0xb55c: - virge->s3d_tri.tzs = val; - break; - case 0xb560: - virge->s3d_tri.TdXdY12 = val; - break; - case 0xb564: - virge->s3d_tri.txend12 = val; - break; - case 0xb568: - virge->s3d_tri.TdXdY01 = val; - break; - case 0xb56c: - virge->s3d_tri.txend01 = val; - break; - case 0xb570: - virge->s3d_tri.TdXdY02 = val; - break; - case 0xb574: - virge->s3d_tri.txs = val; - break; - case 0xb578: - virge->s3d_tri.tys = val; - break; - case 0xb57c: - virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; - virge->s3d_tri.ty12 = val & 0x7ff; - virge->s3d_tri.tlr = val >> 31; - if (virge->s3d_tri.cmd_set & CMD_SET_AE) { - queue_triangle(virge); - } - break; - - default: - break; - } +s3_virge_wait_fifo_idle(virge_t *virge) { + while (!FIFO_EMPTY) { + wake_fifo_thread(virge); + thread_wait_event(virge->fifo_not_full_event, 1); } } @@ -1600,20 +1115,24 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *priv) { virge_t *virge = (virge_t *) priv; - uint8_t ret = 0xff; - - s3_virge_log("[%04X:%08X]: MMIO ReadB addr = %04x\n", CS, cpu_state.pc, addr & 0xffff); + uint8_t ret; switch (addr & 0xffff) { case 0x8504: - virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + if (!virge->virge_busy) + wake_fifo_thread(virge); + ret = virge->subsys_stat; - s3_virge_update_irqs(virge); return ret; case 0x8505: - ret = 0xd0; - if (!virge->s3d_busy) - ret |= 0x20; + ret = 0xc0; + if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) + ret |= 0x10; + else + ret |= 0x30; + + if (!virge->virge_busy) + wake_fifo_thread(virge); return ret; case 0x850c: @@ -1625,55 +1144,8 @@ s3_virge_mmio_read(uint32_t addr, void *priv) ret = virge->fifo_slots_num >> 2; return ret; - case 0x83b0: - case 0x83b1: - case 0x83b2: - case 0x83b3: - case 0x83b4: - case 0x83b5: - case 0x83b6: - case 0x83b7: - case 0x83b8: - case 0x83b9: - case 0x83ba: - case 0x83bb: - case 0x83bc: - case 0x83bd: - case 0x83be: - case 0x83bf: - case 0x83c0: - case 0x83c1: - case 0x83c2: - case 0x83c3: - case 0x83c4: - case 0x83c5: - case 0x83c6: - case 0x83c7: - case 0x83c8: - case 0x83c9: - case 0x83ca: - case 0x83cb: - case 0x83cc: - case 0x83cd: - case 0x83ce: - case 0x83cf: - case 0x83d0: - case 0x83d1: - case 0x83d2: - case 0x83d3: - case 0x83d4: - case 0x83d5: - case 0x83d6: - case 0x83d7: - case 0x83d8: - case 0x83d9: - case 0x83da: - case 0x83db: - case 0x83dc: - case 0x83dd: - case 0x83de: - case 0x83df: - return s3_virge_in(addr & 0x3ff, virge); + case 0x83b0 ... 0x83df: + return s3_virge_in(addr & 0x3ff, priv); case 0x859c: return virge->cmd_dma; @@ -1686,28 +1158,27 @@ s3_virge_mmio_read(uint32_t addr, void *priv) if ((virge->serialport & SERIAL_PORT_SDW) && i2c_gpio_get_sda(virge->i2c)) ret |= SERIAL_PORT_SDR; return ret; - - default: - break; } return 0xff; } + static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *priv) { virge_t *virge = (virge_t *) priv; - uint16_t ret = 0xffff; - - s3_virge_log("[%04X:%08X]: MMIO ReadW addr = %04x\n", CS, cpu_state.pc, addr & 0xfffe); + uint16_t ret; switch (addr & 0xfffe) { case 0x8504: - ret = 0xd000; - if (!virge->s3d_busy) - ret |= 0x2000; - virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + ret = 0xc000; + if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) + ret |= 0x1000; + else + ret |= 0x3000; + ret |= virge->subsys_stat; - s3_virge_update_irqs(virge); + if (!virge->virge_busy) + wake_fifo_thread(virge); return ret; case 0x850c: @@ -1719,19 +1190,15 @@ s3_virge_mmio_read_w(uint32_t addr, void *priv) return virge->cmd_dma; default: - return s3_virge_mmio_read(addr, virge) | (s3_virge_mmio_read(addr + 1, virge) << 8); + return s3_virge_mmio_read(addr, priv) | (s3_virge_mmio_read(addr + 1, priv) << 8); } - return 0xffff; } static uint32_t -s3_virge_mmio_read_l(uint32_t addr, void *priv) -{ +s3_virge_mmio_read_l(uint32_t addr, void *priv) { virge_t *virge = (virge_t *) priv; - uint32_t ret = 0xffffffff; - - s3_virge_log("[%04X:%08X]: MMIO ReadL addr = %04x\n", CS, cpu_state.pc, addr & 0xfffc); + uint32_t ret = 0xffffffff; switch (addr & 0xfffc) { case 0x8180: @@ -1802,12 +1269,15 @@ s3_virge_mmio_read_l(uint32_t addr, void *priv) break; case 0x8504: - ret = 0x0000d000; - if (!virge->s3d_busy) - ret |= 0x00002000; - virge->subsys_stat |= (INT_3DF_EMP | INT_FIFO_EMP); + ret = 0x0000c000; + if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY) + ret |= 0x00001000; + else + ret |= 0x00003000; + ret |= virge->subsys_stat; - s3_virge_update_irqs(virge); + if (!virge->virge_busy) + wake_fifo_thread(virge); break; case 0x850c: @@ -1819,136 +1289,573 @@ s3_virge_mmio_read_l(uint32_t addr, void *priv) ret = virge->cmd_dma_base; break; case 0x8594: + ret = virge->cmd_dma_write_ptr_reg; break; case 0x8598: - ret = virge->dma_ptr; + ret = virge->cmd_dma_read_ptr_reg; + if (ret > virge->cmd_dma_write_ptr_reg) + ret = virge->cmd_dma_write_ptr_reg; break; case 0x859c: - ret = virge->cmd_dma; + ret = 0; /*To prevent DMA overflows.*/ break; case 0xa4d4: + case 0xa8d4: + case 0xacd4: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.src_base; break; case 0xa4d8: + case 0xa8d8: + case 0xacd8: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.dest_base; break; case 0xa4dc: + case 0xa8dc: + case 0xacdc: + s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r; break; case 0xa4e0: + case 0xa8e0: + case 0xace0: + s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b; break; case 0xa4e4: + case 0xa8e4: + case 0xace4: + s3_virge_wait_fifo_idle(virge); ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str; break; case 0xa4e8: case 0xace8: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.mono_pat_0; break; case 0xa4ec: case 0xacec: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.mono_pat_1; break; case 0xa4f0: + case 0xacf0: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.pat_bg_clr; break; case 0xa4f4: + case 0xa8f4: + case 0xacf4: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.pat_fg_clr; break; case 0xa4f8: + s3_virge_wait_fifo_idle(virge); ret = virge->s3d.src_bg_clr; break; - case 0xa4fc: - ret = virge->s3d.src_fg_clr; + case 0xa4fc: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.src_fg_clr; + break; + case 0xa500: + case 0xa900: + case 0xad00: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.cmd_set; + break; + case 0xa504: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; + break; + case 0xa508: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; + break; + case 0xa50c: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; + break; + case 0xa96c: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.lxend0 << 16) | virge->s3d.lxend1; + break; + case 0xa970: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.ldx; + break; + case 0xa974: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.lxstart; + break; + case 0xa978: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.lystart; + break; + case 0xa97c: + s3_virge_wait_fifo_idle(virge); + ret = (virge->s3d.line_dir << 31) | virge->s3d.lycnt; + break; + case 0xad68: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.prdx; + break; + case 0xad6c: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.prxstart; + break; + case 0xad70: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pldx; + break; + case 0xad74: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.plxstart; + break; + case 0xad78: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pystart; + break; + case 0xad7c: + s3_virge_wait_fifo_idle(virge); + ret = virge->s3d.pycnt; + break; + + default: + ret = s3_virge_mmio_read_w(addr, priv) | (s3_virge_mmio_read_w(addr + 2, priv) << 16); + break; + } + + //pclog("MMIO ReadL=%04x, ret=%08x.\n", addr & 0xfffc, ret); + return ret; +} + +static void +s3_virge_mmio_write_fifo_l(virge_t *virge, uint32_t addr, uint32_t val) +{ + switch (addr) { + case 0xa000 ... 0xa1fc: + { + int x = addr & 4; + int y = (addr >> 3) & 7; + int color; + int byte; + uint32_t newaddr = addr; + virge->s3d.pattern_8[y * 8 + x] = val & 0xff; + virge->s3d.pattern_8[y * 8 + x + 1] = val >> 8; + virge->s3d.pattern_8[y * 8 + x + 2] = val >> 16; + virge->s3d.pattern_8[y * 8 + x + 3] = val >> 24; + + x = (addr >> 1) & 6; + y = (addr >> 4) & 7; + virge->s3d.pattern_16[y * 8 + x] = val & 0xffff; + virge->s3d.pattern_16[y * 8 + x + 1] = val >> 16; + + newaddr &= 0x00ff; + for (uint8_t xx = 0; xx < 4; xx++) { + x = ((newaddr + xx) / 3) % 8; + y = ((newaddr + xx) / 24) % 8; + color = ((newaddr + xx) % 3) << 3; + byte = (xx << 3); + virge->s3d.pattern_24[y * 8 + x] &= ~(0xff << color); + virge->s3d.pattern_24[y * 8 + x] |= ((val >> byte) & 0xff) << color; + } + + x = (addr >> 2) & 7; + y = (addr >> 5) & 7; + virge->s3d.pattern_32[y * 8 + x] = val & 0xffffff; + } break; + + case 0xa4d4: + case 0xa8d4: + case 0xacd4: + virge->s3d.src_base = val & ((virge->memory_size == 8) ? + (val & 0x7ffff8) : (val & 0x3ffff8)); + break; + case 0xa4d8: + case 0xa8d8: + case 0xacd8: + virge->s3d.dest_base = val & ((virge->memory_size == 8) ? + (val & 0x7ffff8) : (val & 0x3ffff8)); + break; + case 0xa4dc: + case 0xa8dc: + case 0xacdc: + virge->s3d.clip_l = (val >> 16) & 0x7ff; + virge->s3d.clip_r = val & 0x7ff; + break; + case 0xa4e0: + case 0xa8e0: + case 0xace0: + virge->s3d.clip_t = (val >> 16) & 0x7ff; + virge->s3d.clip_b = val & 0x7ff; + break; + case 0xa4e4: + case 0xa8e4: + case 0xace4: + virge->s3d.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xa4e8: + case 0xace8: + virge->s3d.mono_pat_0 = val; + break; + case 0xa4ec: + case 0xacec: + virge->s3d.mono_pat_1 = val; + break; + case 0xa4f0: + case 0xacf0: + virge->s3d.pat_bg_clr = val; + break; + case 0xa4f4: + case 0xa8f4: + case 0xacf4: + virge->s3d.pat_fg_clr = val; + break; + case 0xa4f8: + virge->s3d.src_bg_clr = val; + break; + case 0xa4fc: + virge->s3d.src_fg_clr = val; + break; + case 0xa500: + case 0xa900: + case 0xad00: + virge->s3d.cmd_set = val; + if (!(val & CMD_SET_AE)) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa504: + virge->s3d.r_width = (val >> 16) & 0x7ff; + virge->s3d.r_height = val & 0x7ff; + break; + case 0xa508: + virge->s3d.rsrc_x = (val >> 16) & 0x7ff; + virge->s3d.rsrc_y = val & 0x7ff; + break; + case 0xa50c: + virge->s3d.rdest_x = (val >> 16) & 0x7ff; + virge->s3d.rdest_y = val & 0x7ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + case 0xa96c: + virge->s3d.lxend0 = (val >> 16) & 0x7ff; + virge->s3d.lxend1 = val & 0x7ff; + break; + case 0xa970: + virge->s3d.ldx = (int32_t)val; + break; + case 0xa974: + virge->s3d.lxstart = val; + break; + case 0xa978: + virge->s3d.lystart = val & 0x7ff; + break; + case 0xa97c: + virge->s3d.lycnt = val & 0x7ff; + virge->s3d.line_dir = val >> 31; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xad68: + virge->s3d.prdx = val; + break; + case 0xad6c: + virge->s3d.prxstart = val; + break; + case 0xad70: + virge->s3d.pldx = val; + break; + case 0xad74: + virge->s3d.plxstart = val; + break; + case 0xad78: + virge->s3d.pystart = val & 0x7ff; + break; + case 0xad7c: + virge->s3d.pycnt = val & 0x300007ff; + if (virge->s3d.cmd_set & CMD_SET_AE) + s3_virge_bitblt(virge, -1, 0); + break; + + case 0xb0d4: + case 0xb4d4: + virge->s3d_tri.z_base = val & ((virge->memory_size == 8) ? + (val & 0x7ffff8) : (val & 0x3ffff8)); + break; + case 0xb0d8: + case 0xb4d8: + virge->s3d_tri.dest_base = val & ((virge->memory_size == 8) ? + (val & 0x7ffff8) : (val & 0x3ffff8)); + break; + case 0xb0dc: + case 0xb4dc: + virge->s3d_tri.clip_l = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_r = val & 0x7ff; + break; + case 0xb0e0: + case 0xb4e0: + virge->s3d_tri.clip_t = (val >> 16) & 0x7ff; + virge->s3d_tri.clip_b = val & 0x7ff; + break; + case 0xb0e4: + case 0xb4e4: + virge->s3d_tri.dest_str = (val >> 16) & 0xff8; + virge->s3d.src_str = val & 0xff8; + break; + case 0xb0e8: + case 0xb4e8: + virge->s3d_tri.z_str = val & 0xff8; + break; + case 0xb4ec: + virge->s3d_tri.tex_base = val & ((virge->memory_size == 8) ? + (val & 0x7ffff8) : (val & 0x3ffff8)); + break; + case 0xb4f0: + virge->s3d_tri.tex_bdr_clr = val & 0xffffff; + break; + case 0xb0f4: + case 0xb4f4: + virge->s3d_tri.fog_b = val & 0xff; + virge->s3d_tri.fog_g = (val >> 8) & 0xff; + virge->s3d_tri.fog_r = (val >> 16) & 0xff; + break; + case 0xb100: + case 0xb500: + virge->s3d_tri.cmd_set = val; + if (!(val & CMD_SET_AE)) + queue_triangle(virge); + break; + case 0xb504: + virge->s3d_tri.tbv = val & 0xfffff; + break; + case 0xb508: + virge->s3d_tri.tbu = val & 0xfffff; + break; + case 0xb50c: + virge->s3d_tri.TdWdX = val; + break; + case 0xb510: + virge->s3d_tri.TdWdY = val; + break; + case 0xb514: + virge->s3d_tri.tws = val; + break; + case 0xb518: + virge->s3d_tri.TdDdX = val; + break; + case 0xb51c: + virge->s3d_tri.TdVdX = val; + break; + case 0xb520: + virge->s3d_tri.TdUdX = val; + break; + case 0xb524: + virge->s3d_tri.TdDdY = val; + break; + case 0xb528: + virge->s3d_tri.TdVdY = val; + break; + case 0xb52c: + virge->s3d_tri.TdUdY = val; + break; + case 0xb530: + virge->s3d_tri.tds = val; + break; + case 0xb534: + virge->s3d_tri.tvs = val; + break; + case 0xb538: + virge->s3d_tri.tus = val; + break; + case 0xb53c: + virge->s3d_tri.TdGdX = val >> 16; + virge->s3d_tri.TdBdX = val & 0xffff; + break; + case 0xb540: + virge->s3d_tri.TdAdX = val >> 16; + virge->s3d_tri.TdRdX = val & 0xffff; + break; + case 0xb544: + virge->s3d_tri.TdGdY = val >> 16; + virge->s3d_tri.TdBdY = val & 0xffff; + break; + case 0xb548: + virge->s3d_tri.TdAdY = val >> 16; + virge->s3d_tri.TdRdY = val & 0xffff; + break; + case 0xb54c: + virge->s3d_tri.tgs = (val >> 16) & 0xffff; + virge->s3d_tri.tbs = val & 0xffff; + break; + case 0xb550: + virge->s3d_tri.tas = (val >> 16) & 0xffff; + virge->s3d_tri.trs = val & 0xffff; + break; + + case 0xb554: + virge->s3d_tri.TdZdX = val; + break; + case 0xb558: + virge->s3d_tri.TdZdY = val; + break; + case 0xb55c: + virge->s3d_tri.tzs = val; + break; + case 0xb560: + virge->s3d_tri.TdXdY12 = val; + break; + case 0xb564: + virge->s3d_tri.txend12 = val; break; - case 0xa500: - ret = virge->s3d.cmd_set; + case 0xb568: + virge->s3d_tri.TdXdY01 = val; break; - case 0xa504: - ret = (virge->s3d.r_width << 16) | virge->s3d.r_height; + case 0xb56c: + virge->s3d_tri.txend01 = val; break; - case 0xa508: - ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y; + case 0xb570: + virge->s3d_tri.TdXdY02 = val; break; - case 0xa50c: - ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y; + case 0xb574: + virge->s3d_tri.txs = val; break; - - default: - ret = s3_virge_mmio_read(addr, virge) | (s3_virge_mmio_read(addr + 1, virge) << 8) | (s3_virge_mmio_read(addr + 2, virge) << 16) | (s3_virge_mmio_read(addr + 3, virge) << 24); + case 0xb578: + virge->s3d_tri.tys = val; break; + case 0xb57c: + virge->s3d_tri.ty01 = (val >> 16) & 0x7ff; + virge->s3d_tri.ty12 = val & 0x7ff; + virge->s3d_tri.tlr = val >> 31; + if (virge->s3d_tri.cmd_set & CMD_SET_AE) + queue_triangle(virge); + break; } +} - s3_virge_log("MMIO ReadL addr = %04x, val = %08x\n", addr & 0xfffc, ret); - return ret; +static void +fifo_thread(void *param) +{ + virge_t *virge = (virge_t *)param; + + while (virge->fifo_thread_run) { + thread_set_event(virge->fifo_not_full_event); + thread_wait_event(virge->wake_fifo_thread, -1); + thread_reset_event(virge->wake_fifo_thread); + virge->virge_busy = 1; + while (!FIFO_EMPTY) { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK]; + uint32_t val = fifo->val; + + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_BYTE: + if (((fifo->addr_type & FIFO_ADDR) & 0xffff) < 0x8000) + s3_virge_bitblt(virge, 8, val); + break; + case FIFO_WRITE_WORD: + if (((fifo->addr_type & FIFO_ADDR) & 0xfffe) < 0x8000) { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16); + else + s3_virge_bitblt(virge, 16, val); + } + break; + case FIFO_WRITE_DWORD: + if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) { + if (virge->s3d.cmd_set & CMD_SET_MS) + s3_virge_bitblt(virge, 32, + ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | + ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); + else + s3_virge_bitblt(virge, 32, val); + } else + s3_virge_mmio_write_fifo_l(virge, (fifo->addr_type & FIFO_ADDR) & 0xfffc, val); + break; + } + + virge->fifo_read_idx++; + fifo->addr_type = FIFO_INVALID; + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(virge->fifo_not_full_event); + + end_time = plat_timer_read(); + virge_time += end_time - start_time; + } + virge->virge_busy = 0; + virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP; + if (virge->cmd_dma) + virge->subsys_stat |= INT_HOST_DONE | INT_CMD_DONE; + + s3_virge_update_irqs(virge); + } +} + +static void +s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK]; + int limit = 0; + + if (type == FIFO_WRITE_DWORD) { + switch (addr & 0xfffc) { + case 0xa500: + if (val & CMD_SET_AE) + limit = 1; + break; + default: + break; + } + } + + if (limit) { + if (FIFO_ENTRIES >= 16) { + thread_reset_event(virge->fifo_not_full_event); + if (FIFO_ENTRIES >= 16) + thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } else { + if (FIFO_FULL) { + thread_reset_event(virge->fifo_not_full_event); + if (FIFO_FULL) + thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/ + } + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + virge->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000) + wake_fifo_thread(virge); + if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8) + wake_fifo_thread(virge); } static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv) { virge_t *virge = (virge_t *) priv; - s3_virge_log("MMIO WriteB addr = %04x, val = %02x\n", addr & 0xffff, val); - if (((addr & 0xffff) >= 0x8590) || ((addr & 0xffff) < 0x8000)) { - if ((addr & 0xffff) == 0xff20) { - virge->serialport = val; - i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); - } else - s3_virge_mmio_fifo_write(addr, val, virge); - } else { + + if ((addr & 0xffff) < 0x8000) + s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE); + else { switch (addr & 0xffff) { - case 0x83b0: - case 0x83b1: - case 0x83b2: - case 0x83b3: - case 0x83b4: - case 0x83b5: - case 0x83b6: - case 0x83b7: - case 0x83b8: - case 0x83b9: - case 0x83ba: - case 0x83bb: - case 0x83bc: - case 0x83bd: - case 0x83be: - case 0x83bf: - case 0x83c0: - case 0x83c1: - case 0x83c2: - case 0x83c3: - case 0x83c4: - case 0x83c5: - case 0x83c6: - case 0x83c7: - case 0x83c8: - case 0x83c9: - case 0x83ca: - case 0x83cb: - case 0x83cc: - case 0x83cd: - case 0x83ce: - case 0x83cf: - case 0x83d0: - case 0x83d1: - case 0x83d2: - case 0x83d3: - case 0x83d4: - case 0x83d5: - case 0x83d6: - case 0x83d7: - case 0x83d8: - case 0x83d9: - case 0x83da: - case 0x83db: - case 0x83dc: - case 0x83dd: - case 0x83de: - case 0x83df: - s3_virge_out(addr & 0x3ff, val, virge); + default: + case 0x83b0 ... 0x83df: + s3_virge_out(addr & 0x3ff, val, priv); break; - default: + case 0xff20: + virge->serialport = val; + i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW)); break; } } @@ -1958,33 +1865,33 @@ static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv) { virge_t *virge = (virge_t *) priv; - s3_virge_log("[%04X:%08X]: MMIO WriteW addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffe, val); - if (((addr & 0xfffe) >= 0x8590) || ((addr & 0xfffe) < 0x8000)) - if ((addr & 0xfffe) == 0xff20) - s3_virge_mmio_write(addr, val, virge); - else - s3_virge_mmio_fifo_write_w(addr, val, virge); + + if ((addr & 0xfffe) < 0x8000) + s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD); else { - if ((addr & 0xfffe) == 0x83d4) { - s3_virge_mmio_write(addr, val, virge); - s3_virge_mmio_write(addr + 1, val >> 8, virge); + switch (addr & 0xfffe) { + default: + case 0x83d4: + s3_virge_mmio_write(addr, val, priv); + s3_virge_mmio_write(addr + 1, val >> 8, priv); + break; + + case 0xff20: + s3_virge_mmio_write(addr, val, priv); + break; } } } static void -s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) -{ +s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) { virge_t *virge = (virge_t *) priv; svga_t *svga = &virge->svga; - s3_virge_log("[%04X:%08X]: MMIO WriteL addr = %04x, val = %04x\n", CS, cpu_state.pc, addr & 0xfffc, val); - if (((addr & 0xfffc) >= 0x8590) || ((addr & 0xfffc) < 0x8000)) - if ((addr & 0xfffc) == 0xff20) - s3_virge_mmio_write(addr, val, virge); - else { - s3_virge_mmio_fifo_write_l(addr, val, virge); - } + if ((addr & 0xfffc) < 0x8000) + s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); + else if ((addr & 0xe000) == 0xa000) + s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD); else { switch (addr & 0xfffc) { case 0x8180: @@ -1996,60 +1903,69 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) virge->streams.chroma_ctrl = val; break; case 0x8190: - virge->streams.sec_ctrl = val; + virge->streams.sec_ctrl = val; virge->streams.dda_horiz_accumulator = val & 0xfff; - if (val & (1 << 11)) - virge->streams.dda_horiz_accumulator |= 0xfffff800; + if (val & 0x1000) + virge->streams.dda_horiz_accumulator |= ~0xfff; + virge->streams.sdif = (val >> 24) & 7; break; case 0x8194: virge->streams.chroma_upper_bound = val; break; case 0x8198: - virge->streams.sec_filter = val; + virge->streams.sec_filter = val; virge->streams.k1_horiz_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k1_horiz_scale |= 0xfffff800; + if (val & 0x800) + virge->streams.k1_horiz_scale |= ~0x7ff; + virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff; - if ((val >> 16) & (1 << 10)) - virge->streams.k2_horiz_scale |= 0xfffff800; + if ((val >> 16) & 0x800) + virge->streams.k2_horiz_scale |= ~0x7ff; + + svga_recalctimings(svga); + svga->fullchange = changeframecount; break; case 0x81a0: virge->streams.blend_ctrl = val; svga_recalctimings(svga); + svga->fullchange = changeframecount; break; case 0x81c0: - virge->streams.pri_fb0 = val & 0x7fffff; - s3_virge_update_buffer(virge); + virge->streams.pri_fb0 = val & ((virge->memory_size == 8) ? + (val & 0x7fffff) : (val & 0x3fffff)); + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81c4: - virge->streams.pri_fb1 = val & 0x7fffff; - s3_virge_update_buffer(virge); + virge->streams.pri_fb1 = ((virge->memory_size == 8) ? + (val & 0x7fffff) : (val & 0x3fffff)); + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81c8: virge->streams.pri_stride = val & 0xfff; - s3_virge_update_buffer(virge); + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81cc: virge->streams.buffer_ctrl = val; - s3_virge_update_buffer(virge); + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81d0: virge->streams.sec_fb0 = val; - s3_virge_update_buffer(virge); + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81d4: virge->streams.sec_fb1 = val; - s3_virge_update_buffer(virge); + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81d8: virge->streams.sec_stride = val; + svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81dc: @@ -2057,47 +1973,50 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) break; case 0x81e0: virge->streams.k1_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k1_vert_scale |= 0xfffff800; + if (val & 0x800) + virge->streams.k1_vert_scale |= ~0x7ff; break; case 0x81e4: virge->streams.k2_vert_scale = val & 0x7ff; - if (val & (1 << 10)) - virge->streams.k2_vert_scale |= 0xfffff800; + if (val & 0x800) + virge->streams.k2_vert_scale |= ~0x7ff; break; case 0x81e8: virge->streams.dda_vert_accumulator = val & 0xfff; - if (val & (1 << 11)) - virge->streams.dda_vert_accumulator |= 0xfffff800; + if (val & 0x1000) + virge->streams.dda_vert_accumulator |= ~0xfff; + + svga_recalctimings(svga); + svga->fullchange = changeframecount; break; case 0x81ec: virge->streams.fifo_ctrl = val; break; case 0x81f0: virge->streams.pri_start = val; - virge->streams.pri_x = (val >> 16) & 0x7ff; - virge->streams.pri_y = val & 0x7ff; + virge->streams.pri_x = (val >> 16) & 0x7ff; + virge->streams.pri_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f4: virge->streams.pri_size = val; - virge->streams.pri_w = (val >> 16) & 0x7ff; - virge->streams.pri_h = val & 0x7ff; + virge->streams.pri_w = (val >> 16) & 0x7ff; + virge->streams.pri_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81f8: virge->streams.sec_start = val; - virge->streams.sec_x = (val >> 16) & 0x7ff; - virge->streams.sec_y = val & 0x7ff; + virge->streams.sec_x = (val >> 16) & 0x7ff; + virge->streams.sec_y = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; case 0x81fc: virge->streams.sec_size = val; - virge->streams.sec_w = (val >> 16) & 0x7ff; - virge->streams.sec_h = val & 0x7ff; + virge->streams.sec_w = (val >> 16) & 0x7ff; + virge->streams.sec_h = val & 0x7ff; svga_recalctimings(svga); svga->fullchange = changeframecount; break; @@ -2113,123 +2032,225 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) s3_virge_updatemapping(virge); break; - default: + case 0x8590: + virge->cmd_dma_base = val; + virge->cmd_dma_buf_size = (val & 2) ? 0x10000 : 0x1000; + virge->cmd_dma_buf_size_mask = virge->cmd_dma_buf_size - 1; + virge->cmd_base_addr = (val & 2) ? (val & 0xffff0000) : (val & 0xfffff000); + break; + + case 0x8594: + virge->cmd_dma_write_ptr_update = val & (1 << 16); + if (virge->cmd_dma_write_ptr_update) { + virge->cmd_dma_write_ptr_reg = (virge->cmd_dma_buf_size == 0x10000) ? (val & 0xffff) : (val & 0xfff); + virge->dma_dbl_words = 0; + virge->dma_data_type = 0; + virge->dma_val = 0; + if (virge->cmd_dma) { + while (virge->cmd_dma_read_ptr_reg != virge->cmd_dma_write_ptr_reg) { + virge->cmd_dma_write_ptr_update = 0; + dma_bm_read(virge->cmd_base_addr + virge->cmd_dma_read_ptr_reg, (uint8_t *)&virge->dma_val, 4, 4); + if (!virge->dma_dbl_words) { + virge->dma_dbl_words = (virge->dma_val & 0xffff); + virge->dma_data_type = !!(virge->dma_val & (1 << 31)); + if (virge->dma_data_type) + virge->dma_mmio_addr = 0; + else + virge->dma_mmio_addr = ((virge->dma_val >> 16) << 2) & 0xfffc; + } else { + s3_virge_mmio_write_l(virge->dma_mmio_addr, virge->dma_val, virge); + virge->dma_dbl_words--; + virge->dma_mmio_addr = (virge->dma_mmio_addr + 4) & 0xfffc; + } + virge->cmd_dma_read_ptr_reg = (virge->cmd_dma_read_ptr_reg + 4) & (virge->cmd_dma_buf_size_mask - 3); + } + } + } + break; + + case 0x8598: + virge->cmd_dma_read_ptr_reg = (virge->cmd_dma_buf_size == 0x10000) ? (val & 0xffff) : (val & 0xfff); + break; + + case 0x859c: + virge->cmd_dma = val & 1; + virge->cmd_dma_write_ptr_reg = 0; + virge->cmd_dma_read_ptr_reg = 0; + break; + + case 0xff20: + s3_virge_mmio_write(addr, val, priv); break; } } } -#define READ(addr, val) \ - { \ - switch (bpp) { \ - case 0: /*8 bpp*/ \ - val = vram[addr & virge->vram_mask]; \ - break; \ - case 1: /*16 bpp*/ \ - val = *(uint16_t *) &vram[addr & virge->vram_mask]; \ - break; \ - case 2: /*24 bpp*/ \ - val = (*(uint32_t *) &vram[addr & virge->vram_mask]) & 0xffffff; \ - break; \ - } \ - } +#define READ(addr, val) \ + do { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ + val = vram[addr & virge->vram_mask]; \ + break; \ + case 1: /*16 bpp*/ \ + val = *(uint16_t *)&vram[addr & virge->vram_mask]; \ + break; \ + case 2: /*24 bpp*/ \ + val = (*(uint32_t *)&vram[addr & virge->vram_mask]) & 0xffffff; \ + break; \ + } \ + } while (0) -#define CLIP(x, y) \ - { \ - if ((virge->s3d.cmd_set & CMD_SET_HC) && (x < virge->s3d.clip_l || x > virge->s3d.clip_r || y < virge->s3d.clip_t || y > virge->s3d.clip_b)) \ - update = 0; \ - } +#define Z_READ(addr) *(uint16_t *)&vram[addr & virge->vram_mask] -#define CLIP_3D(x, y) \ - { \ - if ((s3d_tri->cmd_set & CMD_SET_HC) && (x < s3d_tri->clip_l || x > s3d_tri->clip_r || y < s3d_tri->clip_t || y > s3d_tri->clip_b)) \ - update = 0; \ - } +#define Z_WRITE(addr, val) \ + if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ + *(uint16_t *)&vram[addr & virge->vram_mask] = val -#define MIX() \ - { \ - int c; \ - for (c = 0; c < 24; c++) { \ - int d = (dest & (1 << c)) ? 1 : 0; \ - if (source & (1 << c)) \ - d |= 2; \ - if (pattern & (1 << c)) \ - d |= 4; \ - if (virge->s3d.rop & (1 << d)) \ - out |= (1 << c); \ - } \ - } +#define CLIP(x, y) \ + do { \ + if ((virge->s3d.cmd_set & CMD_SET_HC) && \ + (x < virge->s3d.clip_l || x > virge->s3d.clip_r || \ + y < virge->s3d.clip_t || y > virge->s3d.clip_b)) \ + update = 0; \ + } while (0) -#define WRITE(addr, val) \ - { \ - switch (bpp) { \ - case 0: /*8 bpp*/ \ - vram[addr & virge->vram_mask] = val; \ - svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ - break; \ - case 1: /*16 bpp*/ \ - *(uint16_t *) &vram[addr & virge->vram_mask] = val; \ - svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ - break; \ - case 2: /*24 bpp*/ \ - *(uint32_t *) &vram[addr & virge->vram_mask] = (val & 0xffffff) | (vram[(addr + 3) & virge->vram_mask] << 24); \ - svga->changedvram[(addr & virge->vram_mask) >> 12] = changeframecount; \ - break; \ - } \ - } +#define CLIP_3D(x, y) \ + do { \ + if ((s3d_tri->cmd_set & CMD_SET_HC) && (x < s3d_tri->clip_l || \ + x > s3d_tri->clip_r || y < s3d_tri->clip_t || \ + y > s3d_tri->clip_b)) \ + update = 0; \ + } while (0) + +#define Z_CLIP(Zzb, Zs) \ + do { \ + if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \ + switch ((s3d_tri->cmd_set >> 20) & 7) { \ + case 0: \ + update = 0; \ + break; \ + case 1: \ + if (Zs <= Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 2: \ + if (Zs != Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 3: \ + if (Zs < Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 4: \ + if (Zs >= Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 5: \ + if (Zs == Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 6: \ + if (Zs > Zzb) \ + update = 0; \ + else \ + Zzb = Zs; \ + break; \ + case 7: \ + update = 1; \ + Zzb = Zs; \ + break; \ + } \ + } while (0) + +#define MIX() \ + do { \ + int c; \ + for (c = 0; c < 24; c++) { \ + int d = (dest & (1 << c)) ? 1 : 0; \ + if (source & (1 << c)) \ + d |= 2; \ + if (pattern & (1 << c)) \ + d |= 4; \ + if (virge->s3d.rop & (1 << d)) \ + out |= (1 << c); \ + } \ + } while (0) + +#define WRITE(addr, val) \ + do { \ + switch (bpp) { \ + case 0: /*8 bpp*/ \ + vram[addr & virge->vram_mask] = val; \ + virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ + changeframecount; \ + break; \ + case 1: /*16 bpp*/ \ + *(uint16_t *)&vram[addr & virge->vram_mask] = val; \ + virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ + changeframecount; \ + break; \ + case 2: /*24 bpp*/ \ + *(uint32_t *)&vram[addr & virge->vram_mask] = (val & 0xffffff) |\ + (vram[(addr + 3) & virge->vram_mask] << 24); \ + virge->svga.changedvram[(addr & virge->vram_mask) >> 12] = \ + changeframecount; \ + break; \ + } \ + } while (0) static void -s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) -{ - svga_t *svga = &virge->svga; - uint8_t *vram = virge->svga.vram; - uint32_t mono_pattern[64]; - int count_mask; - int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; - int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; - int bpp; - int x_mul; - int cpu_dat_shift; - const uint32_t *pattern_data; - uint32_t src_fg_clr; - uint32_t src_bg_clr; - uint32_t src_addr; - uint32_t dest_addr; - uint32_t source = 0; - uint32_t dest = 0; - uint32_t pattern; - uint32_t out = 0; - int update; +s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) { + uint8_t *vram = virge->svga.vram; + uint32_t mono_pattern[64]; + int count_mask; + int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1; + int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1; + int bpp; + int x_mul; + int cpu_dat_shift; + uint32_t *pattern_data; + uint32_t src_fg_clr; + uint32_t src_bg_clr; switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK) { case CMD_SET_FORMAT_8: - bpp = 0; - x_mul = 1; + bpp = 0; + x_mul = 1; cpu_dat_shift = 8; - pattern_data = virge->s3d.pattern_8; - src_fg_clr = virge->s3d.src_fg_clr & 0xff; - src_bg_clr = virge->s3d.src_bg_clr & 0xff; + pattern_data = virge->s3d.pattern_8; + src_fg_clr = virge->s3d.src_fg_clr & 0xff; + src_bg_clr = virge->s3d.src_bg_clr & 0xff; break; case CMD_SET_FORMAT_16: - bpp = 1; - x_mul = 2; + bpp = 1; + x_mul = 2; cpu_dat_shift = 16; - pattern_data = virge->s3d.pattern_16; - src_fg_clr = virge->s3d.src_fg_clr & 0xffff; - src_bg_clr = virge->s3d.src_bg_clr & 0xffff; + pattern_data = virge->s3d.pattern_16; + src_fg_clr = virge->s3d.src_fg_clr & 0xffff; + src_bg_clr = virge->s3d.src_bg_clr & 0xffff; break; case CMD_SET_FORMAT_24: default: - bpp = 2; - x_mul = 3; + bpp = 2; + x_mul = 3; cpu_dat_shift = 24; - pattern_data = virge->s3d.pattern_24; - src_fg_clr = virge->s3d.src_fg_clr; - src_bg_clr = virge->s3d.src_bg_clr; + pattern_data = virge->s3d.pattern_24; + src_fg_clr = virge->s3d.src_fg_clr; + src_bg_clr = virge->s3d.src_bg_clr; break; - } - if (virge->s3d.cmd_set & CMD_SET_MP) - pattern_data = mono_pattern; + } + if (virge->s3d.cmd_set & CMD_SET_MP) + pattern_data = mono_pattern; switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK) { case CMD_SET_ITA_BYTE: @@ -2244,52 +2265,51 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) break; } if (virge->s3d.cmd_set & CMD_SET_MP) { - for (uint8_t y = 0; y < 4; y++) { - for (uint8_t x = 0; x < 8; x++) { - if (virge->s3d.mono_pat_0 & (1 << (x + y * 8))) - mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr; - else - mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr; - if (virge->s3d.mono_pat_1 & (1 << (x + y * 8))) - mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr; - else - mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr; - } + int x; + int y; + for (y = 0; y < 4; y++) { + for (x = 0; x < 8; x++) { + if (virge->s3d.mono_pat_0 & (1 << (x + y * 8))) + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_fg_clr; + else + mono_pattern[y * 8 + (7 - x)] = virge->s3d.pat_bg_clr; + if (virge->s3d.mono_pat_1 & (1 << (x + y * 8))) + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_fg_clr; + else + mono_pattern[(y + 4) * 8 + (7 - x)] = virge->s3d.pat_bg_clr; + } } } switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK) { + case CMD_SET_COMMAND_NOP: + break; + case CMD_SET_COMMAND_BITBLT: if (count == -1) { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; - virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.dest_x = virge->s3d.rdest_x; + virge->s3d.dest_y = virge->s3d.rdest_y; + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; virge->s3d.data_left_count = 0; - s3_virge_log("BitBlt start src_x=%i,src_y=%i,dest_x=%i,dest_y=%i,w=%i,h=%i,rop=%02X,src_base=%x,dest_base=%x\n", - virge->s3d.src_x, - virge->s3d.src_y, - virge->s3d.dest_x, - virge->s3d.dest_y, - virge->s3d.w, - virge->s3d.h, - virge->s3d.rop, - virge->s3d.src_base, - virge->s3d.dest_base); - if (virge->s3d.cmd_set & CMD_SET_IDS) return; } if (!virge->s3d.h) return; while (count) { - src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str); - dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - out = 0; - update = 1; + uint32_t src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + + (virge->s3d.src_y * virge->s3d.src_str); + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern; + uint32_t out = 0; + int update = 1; switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS)) { case 0: @@ -2307,18 +2327,18 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) count -= (cpu_dat_shift - virge->s3d.data_left_count); virge->s3d.data_left_count = 0; if (count < cpu_dat_shift) { - virge->s3d.data_left = cpu_dat; + virge->s3d.data_left = cpu_dat; virge->s3d.data_left_count = count; - count = 0; + count = 0; } } else { source = cpu_dat; cpu_dat >>= cpu_dat_shift; count -= cpu_dat_shift; if (count < cpu_dat_shift) { - virge->s3d.data_left = cpu_dat; + virge->s3d.data_left = cpu_dat; virge->s3d.data_left_count = count; - count = 0; + count = 0; } } if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr) @@ -2331,9 +2351,6 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) cpu_dat <<= 1; count--; break; - - default: - break; } CLIP(virge->s3d.dest_x, virge->s3d.dest_y); @@ -2351,9 +2368,9 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.dest_x += x_inc; virge->s3d.dest_x &= 0x7ff; if (!virge->s3d.w) { - virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_x = virge->s3d.rsrc_x; virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; + virge->s3d.w = virge->s3d.r_width; virge->s3d.src_y += y_inc; virge->s3d.dest_y += y_inc; @@ -2370,13 +2387,9 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) cpu_dat <<= (count - (count & count_mask)); count &= count_mask; break; - - default: - break; } - if (!virge->s3d.h) { + if (!virge->s3d.h) return; - } } else virge->s3d.w--; } @@ -2385,27 +2398,23 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) case CMD_SET_COMMAND_RECTFILL: /*No source, pattern = pat_fg_clr*/ if (count == -1) { - virge->s3d.src_x = virge->s3d.rsrc_x; - virge->s3d.src_y = virge->s3d.rsrc_y; + virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_y = virge->s3d.rsrc_y; virge->s3d.dest_x = virge->s3d.rdest_x; virge->s3d.dest_y = virge->s3d.rdest_y; - virge->s3d.w = virge->s3d.r_width; - virge->s3d.h = virge->s3d.r_height; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; - - s3_virge_log("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x, - virge->s3d.dest_y, - virge->s3d.w, - virge->s3d.h, - virge->s3d.rop, virge->s3d.dest_base); + virge->s3d.w = virge->s3d.r_width; + virge->s3d.h = virge->s3d.r_height; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; } while (count && virge->s3d.h) { - source = virge->s3d.pat_fg_clr; - dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - pattern = virge->s3d.pat_fg_clr; - out = 0; - update = 1; + uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern = virge->s3d.pat_fg_clr; + uint32_t out = 0; + int update = 1; CLIP(virge->s3d.dest_x, virge->s3d.dest_y); @@ -2422,18 +2431,17 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.dest_x += x_inc; virge->s3d.dest_x &= 0x7ff; if (!virge->s3d.w) { - virge->s3d.src_x = virge->s3d.rsrc_x; + virge->s3d.src_x = virge->s3d.rsrc_x; virge->s3d.dest_x = virge->s3d.rdest_x; - virge->s3d.w = virge->s3d.r_width; + virge->s3d.w = virge->s3d.r_width; virge->s3d.src_y += y_inc; virge->s3d.dest_y += y_inc; virge->s3d.h--; - if (!virge->s3d.h) { + if (!virge->s3d.h) return; - } } else - virge->s3d.w--; + virge->s3d.w--; count--; } break; @@ -2442,8 +2450,8 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) if (count == -1) { virge->s3d.dest_x = virge->s3d.lxstart; virge->s3d.dest_y = virge->s3d.lystart; - virge->s3d.h = virge->s3d.lycnt; - virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; + virge->s3d.h = virge->s3d.lycnt; + virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; } while (virge->s3d.h) { int x; @@ -2452,7 +2460,8 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) x = virge->s3d.dest_x >> 20; - if (virge->s3d.h == virge->s3d.lycnt && ((virge->s3d.line_dir && x > virge->s3d.lxend0) || (!virge->s3d.line_dir && x < virge->s3d.lxend0))) + if (virge->s3d.h == virge->s3d.lycnt && ((virge->s3d.line_dir && x > virge->s3d.lxend0) || + (!virge->s3d.line_dir && x < virge->s3d.lxend0))) x = virge->s3d.lxend0; if (virge->s3d.h == 1) @@ -2464,17 +2473,22 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) goto skip_line; do { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str); - uint32_t source = 0; - uint32_t dest = 0; + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + + (virge->s3d.dest_y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; uint32_t pattern; - uint32_t out = 0; - int update = 1; + uint32_t out = 0; + int update = 1; - if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && ((virge->s3d.line_dir && x < virge->s3d.lxend0) || (!virge->s3d.line_dir && x > virge->s3d.lxend0))) + if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) && + ((virge->s3d.line_dir && x < virge->s3d.lxend0) || + (!virge->s3d.line_dir && x > virge->s3d.lxend0))) update = 0; - if ((virge->s3d.h == 1 || !first_pixel) && ((virge->s3d.line_dir && x > virge->s3d.lxend1) || (!virge->s3d.line_dir && x < virge->s3d.lxend1))) + if ((virge->s3d.h == 1 || !first_pixel) && + ((virge->s3d.line_dir && x > virge->s3d.lxend1) || + (!virge->s3d.line_dir && x < virge->s3d.lxend1))) update = 0; CLIP(x, virge->s3d.dest_y); @@ -2508,68 +2522,71 @@ s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat) virge->s3d.dest_r = virge->s3d.prxstart; if (virge->s3d.pycnt & (1 << 29)) virge->s3d.dest_l = virge->s3d.plxstart; - virge->s3d.h = virge->s3d.pycnt & 0x7ff; + virge->s3d.h = virge->s3d.pycnt & 0x7ff; virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff; while (virge->s3d.h) { - int x = virge->s3d.dest_l >> 20; - int xend = virge->s3d.dest_r >> 20; - int y = virge->s3d.pystart & 0x7ff; - int xdir = (x < xend) ? 1 : -1; - do { - uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); - uint32_t source = 0; - uint32_t dest = 0; - uint32_t pattern; - uint32_t out = 0; - int update = 1; - - CLIP(x, y); - - if (update) { - READ(dest_addr, dest); - pattern = pattern_data[(y & 7) * 8 + (x & 7)]; - MIX(); - - WRITE(dest_addr, out); - } - - x = (x + xdir) & 0x7ff; - } while (x != (xend + xdir)); - - virge->s3d.dest_l += virge->s3d.pldx; - virge->s3d.dest_r += virge->s3d.prdx; - virge->s3d.h--; - virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; + int x = virge->s3d.dest_l >> 20; + int xend = virge->s3d.dest_r >> 20; + int y = virge->s3d.pystart & 0x7ff; + int xdir = (x < xend) ? 1 : -1; + do { + uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str); + uint32_t source = 0; + uint32_t dest = 0; + uint32_t pattern; + uint32_t out = 0; + int update = 1; + + CLIP(x, y); + + if (update) { + READ(dest_addr, dest); + pattern = pattern_data[(y & 7) * 8 + (x & 7)]; + + MIX(); + + WRITE(dest_addr, out); + } + + x = (x + xdir) & 0x7ff; + } while (x != (xend + xdir)); + + virge->s3d.dest_l += virge->s3d.pldx; + virge->s3d.dest_r += virge->s3d.prdx; + virge->s3d.h--; + virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff; } break; - case CMD_SET_COMMAND_NOP: - break; - default: - break; + fatal("s3_virge_bitblt : blit command %i %08x\n", + (virge->s3d.cmd_set >> 27) & 0xf, virge->s3d.cmd_set); } } -#define RGB15_TO_24(val, r, g, b) \ - b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ - g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ - r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); - -#define RGB24_TO_24(val, r, g, b) \ - b = val & 0xff; \ - g = (val & 0xff00) >> 8; \ - r = (val & 0xff0000) >> 16 - -#define RGB15(r, g, b, dest) \ - if (virge->dithering_enabled) { \ - int add = dither[_y & 3][_x & 3]; \ - int _r = (r > 248) ? 248 : r + add; \ - int _g = (g > 248) ? 248 : g + add; \ - int _b = (b > 248) ? 248 : b + add; \ - dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \ - } else \ - dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10) +#define RGB15_TO_24(val, r, g, b) \ + b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \ + g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \ + r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12); + +#define RGB24_TO_24(val, r, g, b) \ + b = val & 0xff; \ + g = (val & 0xff00) >> 8; \ + r = (val & 0xff0000) >> 16 + +#define RGB15(r, g, b, dest) \ + if (virge->dithering_enabled) { \ + int add = dither[_y & 3][_x & 3]; \ + int _r = (r > 248) ? 248 : r + add; \ + int _g = (g > 248) ? 248 : g + add; \ + int _b = (b > 248) ? 248 : b + add; \ + dest = ((_b >> 3) & 0x1f) | \ + (((_g >> 3) & 0x1f) << 5) | \ + (((_r >> 3) & 0x1f) << 10); \ + } else \ + dest = ((b >> 3) & 0x1f) | \ + (((g >> 3) & 0x1f) << 5) | \ + (((r >> 3) & 0x1f) << 10) #define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) @@ -2578,32 +2595,50 @@ typedef struct rgba_t { } rgba_t; typedef struct s3d_state_t { - int32_t r, g, b, a, u, v, d, w; - - int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w; - - uint32_t base_z; - - uint32_t tbu, tbv; - - uint32_t cmd_set; - int max_d; + int32_t r; + int32_t g; + int32_t b; + int32_t a; + int32_t u; + int32_t v; + int32_t d; + int32_t w; + + int32_t base_r; + int32_t base_g; + int32_t base_b; + int32_t base_a; + int32_t base_u; + int32_t base_v; + int32_t base_d; + int32_t base_w; + + uint32_t base_z; + + uint32_t tbu; + uint32_t tbv; + + uint32_t cmd_set; + int max_d; uint16_t *texture[10]; - uint32_t tex_bdr_clr; + uint32_t tex_bdr_clr; + + int32_t x1; + int32_t x2; - int32_t x1, x2; - int y; + int y; - rgba_t dest_rgba; + rgba_t dest_rgba; } s3d_state_t; typedef struct s3d_texture_state_t { - int level; - int texture_shift; + int level; + int texture_shift; - int32_t u, v; + int32_t u; + int32_t v; } s3d_texture_state_t; static void (*tex_read)(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out); @@ -2617,10 +2652,10 @@ static int _x; static int _y; static void -tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; +tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12); out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7); @@ -2629,10 +2664,10 @@ tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out } static void -tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; +tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) val = state->tex_bdr_clr; @@ -2644,10 +2679,10 @@ tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba } static void -tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; +tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8); out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4); @@ -2656,10 +2691,10 @@ tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out } static void -tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint16_t val = state->texture[texture_state->level][offset]; +tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint16_t val = state->texture[texture_state->level][offset]; if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) val = state->tex_bdr_clr; @@ -2671,21 +2706,22 @@ tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba } static void -tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint32_t val = ((uint32_t *) state->texture[texture_state->level])[offset]; +tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; out->r = (val >> 16) & 0xff; out->g = (val >> 8) & 0xff; out->b = val & 0xff; out->a = (val >> 24) & 0xff; } + static void -tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) -{ - int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); - uint32_t val = ((uint32_t *) state->texture[texture_state->level])[offset]; +tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out) { + int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) + + (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level); + uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset]; if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000) val = state->tex_bdr_clr; @@ -2697,21 +2733,19 @@ tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba } static void -tex_sample_normal(s3d_state_t *state) -{ +tex_sample_normal(s3d_state_t *state) { s3d_texture_state_t texture_state; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_normal_filter(s3d_state_t *state) -{ +tex_sample_normal_filter(s3d_state_t *state) { s3d_texture_state_t texture_state; int tex_offset; rgba_t tex_samples[4]; @@ -2719,9 +2753,9 @@ tex_sample_normal_filter(s3d_state_t *state) int dv; int d[4]; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = state->u + state->tbu; texture_state.v = state->v + state->tbv; @@ -2746,30 +2780,32 @@ tex_sample_normal_filter(s3d_state_t *state) d[2] = (256 - du) * dv; d[3] = du * dv; - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } static void -tex_sample_mipmap(s3d_state_t *state) -{ +tex_sample_mipmap(s3d_state_t *state) { s3d_texture_state_t texture_state; texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = state->u + state->tbu; - texture_state.v = state->v + state->tbv; + texture_state.u = state->u + state->tbu; + texture_state.v = state->v + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_mipmap_filter(s3d_state_t *state) -{ +tex_sample_mipmap_filter(s3d_state_t *state) { s3d_texture_state_t texture_state; int tex_offset; rgba_t tex_samples[4]; @@ -2781,7 +2817,7 @@ tex_sample_mipmap_filter(s3d_state_t *state) if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = state->u + state->tbu; texture_state.v = state->v + state->tbv; @@ -2806,34 +2842,36 @@ tex_sample_mipmap_filter(s3d_state_t *state) d[2] = (256 - du) * dv; d[3] = du * dv; - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } static void -tex_sample_persp_normal(s3d_state_t *state) -{ +tex_sample_persp_normal(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_normal_filter(s3d_state_t *state) -{ +tex_sample_persp_normal_filter(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -2843,14 +2881,14 @@ tex_sample_persp_normal_filter(s3d_state_t *state) int d[4]; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -2875,34 +2913,36 @@ tex_sample_persp_normal_filter(s3d_state_t *state) d[2] = (256 - du) * dv; d[3] = du * dv; - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } static void -tex_sample_persp_normal_375(s3d_state_t *state) -{ +tex_sample_persp_normal_375(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_normal_filter_375(s3d_state_t *state) -{ +tex_sample_persp_normal_filter_375(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -2912,14 +2952,14 @@ tex_sample_persp_normal_filter_375(s3d_state_t *state) int d[4]; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; - texture_state.level = state->max_d; + texture_state.level = state->max_d; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -2944,36 +2984,38 @@ tex_sample_persp_normal_filter_375(s3d_state_t *state) d[2] = (256 - du) * dv; d[3] = du * dv; - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } static void -tex_sample_persp_mipmap(s3d_state_t *state) -{ +tex_sample_persp_mipmap(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; - texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_mipmap_filter(s3d_state_t *state) -{ +tex_sample_persp_mipmap_filter(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -2983,16 +3025,16 @@ tex_sample_persp_mipmap_filter(s3d_state_t *state) int d[4]; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (12 + state->max_d)) + state->tbu; - v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (12 + state->max_d)) + state->tbv; + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv; texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -3017,36 +3059,38 @@ tex_sample_persp_mipmap_filter(s3d_state_t *state) d[2] = (256 - du) * dv; d[3] = du * dv; - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } static void -tex_sample_persp_mipmap_375(s3d_state_t *state) -{ +tex_sample_persp_mipmap_375(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - texture_state.u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; - texture_state.v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; + texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; tex_read(state, &texture_state, &state->dest_rgba); } static void -tex_sample_persp_mipmap_filter_375(s3d_state_t *state) -{ +tex_sample_persp_mipmap_filter_375(s3d_state_t *state) { s3d_texture_state_t texture_state; - int32_t w = 0; + int32_t w = 0; int32_t u; int32_t v; int tex_offset; @@ -3056,16 +3100,16 @@ tex_sample_persp_mipmap_filter_375(s3d_state_t *state) int d[4]; if (state->w) - w = (int32_t) (((1ULL << 27) << 19) / (int64_t) state->w); + w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w); - u = (int32_t) (((int64_t) state->u * (int64_t) w) >> (8 + state->max_d)) + state->tbu; - v = (int32_t) (((int64_t) state->v * (int64_t) w) >> (8 + state->max_d)) + state->tbv; + u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu; + v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv; texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf); if (texture_state.level < 0) texture_state.level = 0; texture_state.texture_shift = 18 + (9 - texture_state.level); - tex_offset = 1 << texture_state.texture_shift; + tex_offset = 1 << texture_state.texture_shift; texture_state.u = u; texture_state.v = v; @@ -3090,47 +3134,50 @@ tex_sample_persp_mipmap_filter_375(s3d_state_t *state) d[2] = (256 - du) * dv; d[3] = du * dv; - state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; - state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; - state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; - state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; + state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16; + state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16; + state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16; + state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16; } -#define CLAMP(x) \ - do { \ - if ((x) & ~0xff) \ - x = ((x) < 0) ? 0 : 0xff; \ +#define CLAMP(x) \ + do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ } while (0) -#define CLAMP_RGBA(r, g, b, a) \ - if ((r) & ~0xff) \ - r = ((r) < 0) ? 0 : 0xff; \ - if ((g) & ~0xff) \ - g = ((g) < 0) ? 0 : 0xff; \ - if ((b) & ~0xff) \ - b = ((b) < 0) ? 0 : 0xff; \ - if ((a) & ~0xff) \ - a = ((a) < 0) ? 0 : 0xff; - -#define CLAMP_RGB(r, g, b) \ - do { \ - if ((r) < 0) \ - r = 0; \ - if ((r) > 0xff) \ - r = 0xff; \ - if ((g) < 0) \ - g = 0; \ - if ((g) > 0xff) \ - g = 0xff; \ - if ((b) < 0) \ - b = 0; \ - if ((b) > 0xff) \ - b = 0xff; \ +#define CLAMP_RGBA(r, g, b, a) \ + if ((r) & ~0xff) \ + r = ((r) < 0) ? 0 : 0xff; \ + if ((g) & ~0xff) \ + g = ((g) < 0) ? 0 : 0xff; \ + if ((b) & ~0xff) \ + b = ((b) < 0) ? 0 : 0xff; \ + if ((a) & ~0xff) \ + a = ((a) < 0) ? 0 : 0xff; + +#define CLAMP_RGB(r, g, b) \ + do { \ + if ((r) < 0) \ + r = 0; \ + if ((r) > 0xff) \ + r = 0xff; \ + if ((g) < 0) \ + g = 0; \ + if ((g) > 0xff) \ + g = 0xff; \ + if ((b) < 0) \ + b = 0; \ + if ((b) > 0xff) \ + b = 0xff; \ } while (0) static void -dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) -{ +dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) { state->dest_rgba.r = state->r >> 7; CLAMP(state->dest_rgba.r); @@ -3145,8 +3192,7 @@ dest_pixel_gouraud_shaded_triangle(s3d_state_t *state) } static void -dest_pixel_unlit_texture_triangle(s3d_state_t *state) -{ +dest_pixel_unlit_texture_triangle(s3d_state_t *state) { tex_sample(state); if (state->cmd_set & CMD_SET_ABC_SRC) @@ -3154,8 +3200,7 @@ dest_pixel_unlit_texture_triangle(s3d_state_t *state) } static void -dest_pixel_lit_texture_decal(s3d_state_t *state) -{ +dest_pixel_lit_texture_decal(s3d_state_t *state) { tex_sample(state); if (state->cmd_set & CMD_SET_ABC_SRC) @@ -3163,8 +3208,7 @@ dest_pixel_lit_texture_decal(s3d_state_t *state) } static void -dest_pixel_lit_texture_reflection(s3d_state_t *state) -{ +dest_pixel_lit_texture_reflection(s3d_state_t *state) { tex_sample(state); state->dest_rgba.r += (state->r >> 7); @@ -3177,8 +3221,7 @@ dest_pixel_lit_texture_reflection(s3d_state_t *state) } static void -dest_pixel_lit_texture_modulate(s3d_state_t *state) -{ +dest_pixel_lit_texture_modulate(s3d_state_t *state) { int r = state->r >> 7; int g = state->g >> 7; int b = state->b >> 7; @@ -3189,300 +3232,233 @@ dest_pixel_lit_texture_modulate(s3d_state_t *state) CLAMP_RGBA(r, g, b, a); state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8; - state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; - state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; - - if (state->cmd_set & CMD_SET_ABC_SRC) - state->dest_rgba.a = a; -} - -static void -tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) -{ - svga_t *svga = &virge->svga; - uint8_t *vram = svga->vram; - - int x_dir = s3d_tri->tlr ? 1 : -1; - - int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); - - int y_count = yc; - - int bpp = (s3d_tri->cmd_set >> 2) & 7; - - uint32_t dest_offset = 0; - uint32_t z_offset = 0; - - uint32_t src_col; - int src_r = 0; - int src_g = 0; - int src_b = 0; - - int x; - int xe; - uint32_t z; - - uint32_t dest_addr; - uint32_t z_addr; - int dx; - int x_offset; - int xz_offset; - - int update; - uint16_t src_z = 0; - - if (s3d_tri->cmd_set & CMD_SET_HC) { - if (state->y < s3d_tri->clip_t) - return; - if (state->y > s3d_tri->clip_b) { - int diff_y = state->y - s3d_tri->clip_b; - - if (diff_y > y_count) - diff_y = y_count; - - state->base_u += (s3d_tri->TdUdY * diff_y); - state->base_v += (s3d_tri->TdVdY * diff_y); - state->base_z += (s3d_tri->TdZdY * diff_y); - state->base_r += (s3d_tri->TdRdY * diff_y); - state->base_g += (s3d_tri->TdGdY * diff_y); - state->base_b += (s3d_tri->TdBdY * diff_y); - state->base_a += (s3d_tri->TdAdY * diff_y); - state->base_d += (s3d_tri->TdDdY * diff_y); - state->base_w += (s3d_tri->TdWdY * diff_y); - state->x1 += (dx1 * diff_y); - state->x2 += (dx2 * diff_y); - state->y -= diff_y; - dest_offset -= s3d_tri->dest_str * diff_y; - z_offset -= s3d_tri->z_str; - y_count -= diff_y; - } - if ((state->y - y_count) < s3d_tri->clip_t) - y_count = (state->y - s3d_tri->clip_t) + 1; - } - - dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); - z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); - - while (y_count > 0) { - x = (state->x1 + ((1 << 20) - 1)) >> 20; - xe = (state->x2 + ((1 << 20) - 1)) >> 20; - z = (state->base_z > 0) ? (state->base_z << 1) : 0; - if (x_dir < 0) { - x--; - xe--; - } - - if (((x != xe) && ((x_dir > 0) && (x < xe))) || ((x_dir < 0) && (x > xe))) { - dx = (x_dir > 0) ? ((31 - ((state->x1 - 1) >> 15)) & 0x1f) : (((state->x1 - 1) >> 15) & 0x1f); - x_offset = x_dir * (bpp + 1); - xz_offset = x_dir << 1; - if (x_dir > 0) - dx += 1; - state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); - state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); - state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); - state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); - state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); - state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); - state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); - state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); - z += ((s3d_tri->TdZdX * dx) >> 5); - - if (s3d_tri->cmd_set & CMD_SET_HC) { - if (x_dir > 0) { - if (x > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - xe = s3d_tri->clip_r + 1; - if (x < s3d_tri->clip_l) { - int diff_x = s3d_tri->clip_l - x; - - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); - - x = s3d_tri->clip_l; - } - } else { - if (x < s3d_tri->clip_l) - goto tri_skip_line; - if (xe > s3d_tri->clip_r) - goto tri_skip_line; - if (xe < s3d_tri->clip_l) - xe = s3d_tri->clip_l - 1; - if (x > s3d_tri->clip_r) { - int diff_x = x - s3d_tri->clip_r; - - z += (s3d_tri->TdZdX * diff_x); - state->u += (s3d_tri->TdUdX * diff_x); - state->v += (s3d_tri->TdVdX * diff_x); - state->r += (s3d_tri->TdRdX * diff_x); - state->g += (s3d_tri->TdGdX * diff_x); - state->b += (s3d_tri->TdBdX * diff_x); - state->a += (s3d_tri->TdAdX * diff_x); - state->d += (s3d_tri->TdDdX * diff_x); - state->w += (s3d_tri->TdWdX * diff_x); - - x = s3d_tri->clip_r; - } - } - } - - svga->changedvram[(dest_offset & virge->vram_mask) >> 12] = changeframecount; - - dest_addr = dest_offset + (x * (bpp + 1)); - z_addr = z_offset + (x << 1); - - x &= 0xfff; - xe &= 0xfff; - - while (x != xe) { - update = 1; - _x = x; - _y = state->y; - - if (use_z) { - src_z = *(uint16_t *) &vram[z_addr & virge->vram_mask]; - switch ((s3d_tri->cmd_set >> 20) & 7) { - case 0: - update = 0; - break; - case 1: - if ((z >> 16) > src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 2: - if ((z >> 16) == src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 3: - if ((z >> 16) >= src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 4: - if ((z >> 16) < src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 5: - if ((z >> 16) != src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 6: - if ((z >> 16) <= src_z) { - src_z = (z >> 16); - } else - update = 0; - break; - case 7: - src_z = (z >> 16); - break; - - default: - break; - } - } - - if (update) { - uint32_t dest_col; - - dest_pixel(state); - - if (s3d_tri->cmd_set & CMD_SET_FE) { - int a = state->a >> 7; - state->dest_rgba.r = ((state->dest_rgba.r * a) + (s3d_tri->fog_r * (255 - a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; - } + state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8; + state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8; - if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) { - switch (bpp) { - case 0: /*8 bpp*/ - /*TODO: Not implemented yet*/ - break; - case 1: /*16 bpp*/ - src_col = *(uint16_t *) &vram[dest_addr & virge->vram_mask]; - RGB15_TO_24(src_col, src_r, src_g, src_b); - break; - case 2: /*24 bpp*/ - src_col = (*(uint32_t *) &vram[dest_addr & virge->vram_mask]) & 0xffffff; - RGB24_TO_24(src_col, src_r, src_g, src_b); - break; - - default: - break; - } + if (state->cmd_set & CMD_SET_ABC_SRC) + state->dest_rgba.a = a; +} - state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255; - state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255; - } +static void +tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2) { + uint8_t *vram = virge->svga.vram; + int x_dir = s3d_tri->tlr ? 1 : -1; + int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE); + int y_count = yc; + int bpp = (s3d_tri->cmd_set >> 2) & 7; + uint32_t dest_offset; + uint32_t z_offset; - switch (bpp) { - case 0: /*8 bpp*/ - /*TODO: Not implemented yet*/ - break; - case 1: /*16 bpp*/ - RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); - *(uint16_t *) &vram[dest_addr & virge->vram_mask] = dest_col; - svga->changedvram[(dest_addr & virge->vram_mask) >> 12] = changeframecount; - break; - case 2: /*24 bpp*/ - dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); - *(uint8_t *) &vram[dest_addr & virge->vram_mask] = dest_col & 0xff; - *(uint8_t *) &vram[(dest_addr + 1) & virge->vram_mask] = (dest_col >> 8) & 0xff; - *(uint8_t *) &vram[(dest_addr + 2) & virge->vram_mask] = (dest_col >> 16) & 0xff; - svga->changedvram[(dest_addr & virge->vram_mask) >> 12] = changeframecount; - break; + dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str); + z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str); - default: - break; - } - } + if (s3d_tri->cmd_set & CMD_SET_HC) { + if (state->y < s3d_tri->clip_t) + return; + if (state->y > s3d_tri->clip_b) { + int diff_y = state->y - s3d_tri->clip_b; - if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) { - *(uint16_t *) &vram[z_addr & virge->vram_mask] = src_z; - svga->changedvram[(z_addr & virge->vram_mask) >> 12] = changeframecount; - } + if (diff_y > y_count) + diff_y = y_count; - z += s3d_tri->TdZdX; - state->u += s3d_tri->TdUdX; - state->v += s3d_tri->TdVdX; - state->r += s3d_tri->TdRdX; - state->g += s3d_tri->TdGdX; - state->b += s3d_tri->TdBdX; - state->a += s3d_tri->TdAdX; - state->d += s3d_tri->TdDdX; - state->w += s3d_tri->TdWdX; - dest_addr += x_offset; - z_addr += xz_offset; - - x = (x + x_dir) & 0xfff; - } + state->base_u += (s3d_tri->TdUdY * diff_y); + state->base_v += (s3d_tri->TdVdY * diff_y); + state->base_z += (s3d_tri->TdZdY * diff_y); + state->base_r += (s3d_tri->TdRdY * diff_y); + state->base_g += (s3d_tri->TdGdY * diff_y); + state->base_b += (s3d_tri->TdBdY * diff_y); + state->base_a += (s3d_tri->TdAdY * diff_y); + state->base_d += (s3d_tri->TdDdY * diff_y); + state->base_w += (s3d_tri->TdWdY * diff_y); + state->x1 += (dx1 * diff_y); + state->x2 += (dx2 * diff_y); + state->y -= diff_y; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; + y_count -= diff_y; } + if ((state->y - y_count) < s3d_tri->clip_t) + y_count = (state->y - s3d_tri->clip_t) + 1; + } - y_count--; + for (; y_count > 0; y_count--) { + int x = (state->x1 + ((1 << 20) - 1)) >> 20; + int xe = (state->x2 + ((1 << 20) - 1)) >> 20; + uint32_t z = (state->base_z > 0) ? (state->base_z << 1) : 0; + + if (x_dir < 0) { + x--; + xe--; + } + + if (x != xe && ((x_dir > 0 && x < xe) || (x_dir < 0 && x > xe))) { + uint32_t dest_addr; + uint32_t z_addr; + int dx = (x_dir > 0) ? ((31 - ((state->x1 - 1) >> 15)) & 0x1f) : + (((state->x1 - 1) >> 15) & 0x1f); + int x_offset = x_dir * (bpp + 1); + int xz_offset = x_dir << 1; + + if (x_dir > 0) + dx += 1; + + state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5); + state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5); + state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5); + state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5); + state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5); + state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5); + state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5); + state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5); + z += ((s3d_tri->TdZdX * dx) >> 5); + + if (s3d_tri->cmd_set & CMD_SET_HC) { + if (x_dir > 0) { + if (x > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + xe = s3d_tri->clip_r + 1; + if (x < s3d_tri->clip_l) { + int diff_x = s3d_tri->clip_l - x; + + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); + + x = s3d_tri->clip_l; + } + } else { + if (x < s3d_tri->clip_l) + goto tri_skip_line; + if (xe > s3d_tri->clip_r) + goto tri_skip_line; + if (xe < s3d_tri->clip_l) + xe = s3d_tri->clip_l - 1; + if (x > s3d_tri->clip_r) { + int diff_x = x - s3d_tri->clip_r; + + z += (s3d_tri->TdZdX * diff_x); + state->u += (s3d_tri->TdUdX * diff_x); + state->v += (s3d_tri->TdVdX * diff_x); + state->r += (s3d_tri->TdRdX * diff_x); + state->g += (s3d_tri->TdGdX * diff_x); + state->b += (s3d_tri->TdBdX * diff_x); + state->a += (s3d_tri->TdAdX * diff_x); + state->d += (s3d_tri->TdDdX * diff_x); + state->w += (s3d_tri->TdWdX * diff_x); + + x = s3d_tri->clip_r; + } + } + } + + virge->svga.changedvram[(dest_offset & virge->vram_mask) >> 12] = changeframecount; + + dest_addr = dest_offset + (x * (bpp + 1)); + z_addr = z_offset + (x << 1); + + x &= 0xfff; + xe &= 0xfff; + + for (; x != xe; x = (x + x_dir) & 0xfff) { + int update = 1; + uint16_t src_z = 0; + + _x = x; + _y = state->y; + + if (use_z) { + src_z = Z_READ(z_addr); + Z_CLIP(src_z, z >> 16); + } + + if (update) { + uint32_t dest_col; + + dest_pixel(state); + + if (s3d_tri->cmd_set & CMD_SET_FE) { + int a = state->a >> 7; + state->dest_rgba.r = ((state->dest_rgba.r * a) + (s3d_tri->fog_r * (255 - a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * a) + (s3d_tri->fog_g * (255 - a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * a) + (s3d_tri->fog_b * (255 - a))) / 255; + } + + if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE) { + uint32_t src_col; + int src_r = 0; + uint32_t src_g = 0; + uint32_t src_b = 0; + + + switch (bpp) { + case 0: /*8 bpp*/ + /*Not implemented yet*/ + break; + case 1: /*16 bpp*/ + src_col = *(uint16_t *)&vram[dest_addr & virge->vram_mask]; + RGB15_TO_24(src_col, src_r, src_g, src_b); + break; + case 2: /*24 bpp*/ + src_col = (*(uint32_t *)&vram[dest_addr & virge->vram_mask]) & 0xffffff; + RGB24_TO_24(src_col, src_r, src_g, src_b); + break; + } + + state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + + (src_r * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + + (src_g * (255 - state->dest_rgba.a))) / 255; + state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + + (src_b * (255 - state->dest_rgba.a))) / 255; + } + + switch (bpp) { + case 0: /*8 bpp*/ + /*Not implemented yet*/ + break; + case 1: /*16 bpp*/ + RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col); + *(uint16_t *)&vram[dest_addr] = dest_col; + break; + case 2: /*24 bpp*/ + dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b); + *(uint8_t *)&vram[dest_addr] = dest_col & 0xff; + *(uint8_t *)&vram[dest_addr + 1] = (dest_col >> 8) & 0xff; + *(uint8_t *)&vram[dest_addr + 2] = (dest_col >> 16) & 0xff; + break; + } + + if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP)) + Z_WRITE(z_addr, src_z); + } + + z += s3d_tri->TdZdX; + state->u += s3d_tri->TdUdX; + state->v += s3d_tri->TdVdX; + state->r += s3d_tri->TdRdX; + state->g += s3d_tri->TdGdX; + state->b += s3d_tri->TdBdX; + state->a += s3d_tri->TdAdX; + state->d += s3d_tri->TdDdX; + state->w += s3d_tri->TdWdX; + dest_addr += x_offset; + z_addr += xz_offset; + virge->pixel_count++; + } + } tri_skip_line: - state->x1 += dx1; - state->x2 += dx2; + state->x1 += dx1; + state->x2 += dx2; state->base_u += s3d_tri->TdUdY; state->base_v += s3d_tri->TdVdY; state->base_z += s3d_tri->TdZdY; @@ -3493,31 +3469,22 @@ tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int state->base_d += s3d_tri->TdDdY; state->base_w += s3d_tri->TdWdY; state->y--; - dest_offset -= s3d_tri->dest_str; - z_offset -= s3d_tri->z_str; + dest_offset -= s3d_tri->dest_str; + z_offset -= s3d_tri->z_str; } } -static int tex_size[8] = { - 4 * 2, - 2 * 2, - 2 * 2, - 1 * 2, - 2 / 1, - 2 / 1, - 1 * 2, - 1 * 2 -}; +static int tex_size[8] = {4 * 2, 2 * 2, 2 * 2, 1 * 2, 2 / 1, 2 / 1, 1 * 2, 1 * 2}; static void -s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) -{ +s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) { s3d_state_t state; - uint32_t tex_base; + uint32_t tex_base; + int c; - uint64_t start_time = plat_timer_read(); - uint64_t end_time; + uint64_t start_time = plat_timer_read(); + uint64_t end_time; state.tbu = s3d_tri->tbu << 11; state.tbv = s3d_tri->tbv << 11; @@ -3531,18 +3498,18 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.base_u = s3d_tri->tus; state.base_v = s3d_tri->tvs; state.base_z = s3d_tri->tzs; - state.base_r = (int32_t) s3d_tri->trs; - state.base_g = (int32_t) s3d_tri->tgs; - state.base_b = (int32_t) s3d_tri->tbs; - state.base_a = (int32_t) s3d_tri->tas; + state.base_r = (int32_t)s3d_tri->trs; + state.base_g = (int32_t)s3d_tri->tgs; + state.base_b = (int32_t)s3d_tri->tbs; + state.base_a = (int32_t)s3d_tri->tas; state.base_d = s3d_tri->tds; state.base_w = s3d_tri->tws; tex_base = s3d_tri->tex_base; - for (int c = 9; c >= 0; c--) { - state.texture[c] = (uint16_t *) &virge->svga.vram[tex_base]; - if (c <= state.max_d) - tex_base += ((1 << (c * 2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; + for (c = 9; c >= 0; c--) { + state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base]; + if (c <= state.max_d) + tex_base += ((1 << (c * 2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2; } switch ((s3d_tri->cmd_set >> 27) & 0xf) { @@ -3562,7 +3529,6 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) dest_pixel = dest_pixel_lit_texture_decal; break; default: - s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; } break; @@ -3571,7 +3537,6 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) dest_pixel = dest_pixel_unlit_texture_triangle; break; default: - s3_virge_log("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf); return; } @@ -3594,34 +3559,35 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) break; case (0 | 8): case (1 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) + if ((virge->chip == S3_VIRGEDX) || (virge->chip >= S3_VIRGEGX2)) tex_sample = tex_sample_persp_mipmap_375; else tex_sample = tex_sample_persp_mipmap; break; case (2 | 8): case (3 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) - tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375; + if ((virge->chip == S3_VIRGEDX) || (virge->chip >= S3_VIRGEGX2)) + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : + tex_sample_persp_mipmap_375; else - tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap; + tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : + tex_sample_persp_mipmap; break; case (4 | 8): case (5 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) + if ((virge->chip == S3_VIRGEDX) || (virge->chip >= S3_VIRGEGX2)) tex_sample = tex_sample_persp_normal_375; else tex_sample = tex_sample_persp_normal; break; case (6 | 8): case (7 | 8): - if (virge->chip == S3_VIRGEDX || virge->chip >= S3_VIRGEGX2) - tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375; + if ((virge->chip == S3_VIRGEDX) || (virge->chip >= S3_VIRGEGX2)) + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : + tex_sample_persp_normal_375; else - tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal; - break; - - default: + tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : + tex_sample_persp_normal; break; } @@ -3636,7 +3602,6 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; default: - s3_virge_log("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7); tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap; break; } @@ -3648,21 +3613,58 @@ s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri) state.x2 = s3d_tri->txend12; tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12); + virge->tri_count++; + end_time = plat_timer_read(); - virge->blitter_time += end_time - start_time; + virge_time += end_time - start_time; +} + +static void +render_thread(void *param) +{ + virge_t *virge = (virge_t *)param; + + while (virge->render_thread_run) { + thread_wait_event(virge->wake_render_thread, -1); + thread_reset_event(virge->wake_render_thread); + virge->s3d_busy = 1; + while (!RB_EMPTY) { + s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]); + virge->s3d_read_idx++; + + if (RB_ENTRIES == RB_MASK) + thread_set_event(virge->not_full_event); + } + virge->s3d_busy = 0; + virge->subsys_stat |= INT_S3D_DONE; + s3_virge_update_irqs(virge); + } } static void -s3_virge_hwcursor_draw(svga_t *svga, int displine) +queue_triangle(virge_t *virge) { - const virge_t *virge = (virge_t *) svga->priv; - uint16_t dat[2]; - int xx; - int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; - uint32_t fg; - uint32_t bg; - uint32_t vram_mask = virge->vram_mask; + if (RB_FULL) { + thread_reset_event(virge->not_full_event); + if (RB_FULL) + thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/ + } + virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri; + virge->s3d_write_idx++; + if (!virge->s3d_busy) + thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/ +} + +static void s3_virge_hwcursor_draw(svga_t *svga, int displine) { + virge_t *virge = (virge_t *) svga->priv; + int x; + uint16_t dat[2] = { 0, 0 }; + int xx; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + uint32_t fg; + uint32_t bg; + uint32_t vram_mask = virge->vram_mask; if (svga->interlace && svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; @@ -3699,13 +3701,16 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) break; } - for (uint8_t x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[svga->hwcursor_latch.addr & vram_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & vram_mask]; - dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & vram_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & vram_mask]; + for (x = 0; x < 64; x += 16) { + dat[0] = (svga->vram[svga->hwcursor_latch.addr & vram_mask] << 8) | + svga->vram[(svga->hwcursor_latch.addr + 1) & vram_mask]; + dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & vram_mask] << 8) | + svga->vram[(svga->hwcursor_latch.addr + 3) & vram_mask]; + if (svga->crtc[0x55] & 0x10) { /*X11*/ for (xx = 0; xx < 16; xx++) { - if (offset >= 0) { + if (offset >= svga->hwcursor_latch.x) { if (virge->chip == S3_VIRGEGX2) dat[0] ^= 0x8000; @@ -3714,13 +3719,14 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) } offset++; + dat[0] <<= 1; dat[1] <<= 1; } } else { /*Windows*/ for (xx = 0; xx < 16; xx++) { - if (offset >= 0) { + if (offset >= svga->hwcursor_latch.x) { if (!(dat[0] & 0x8000)) buffer32->line[displine][offset + svga->x_add] = (dat[1] & 0x8000) ? fg : bg; else if (dat[1] & 0x8000) @@ -3728,101 +3734,109 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) } offset++; + dat[0] <<= 1; dat[1] <<= 1; } } + svga->hwcursor_latch.addr += 4; } + if (svga->interlace && !svga->hwcursor_oddeven) svga->hwcursor_latch.addr += 16; } -#define DECODE_YCbCr() \ - do { \ - int c; \ - \ - for (c = 0; c < 2; c++) { \ - uint8_t y1, y2; \ - int8_t Cr, Cb; \ - int dR, dG, dB; \ - \ - y1 = src[0]; \ - Cr = src[1] - 0x80; \ - y2 = src[2]; \ - Cb = src[3] - 0x80; \ - src += 4; \ - \ - dR = (359 * Cr) >> 8; \ - dG = (88 * Cb + 183 * Cr) >> 8; \ - dB = (453 * Cb) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write + 1] = y2 + dR; \ - CLAMP(r[x_write + 1]); \ - g[x_write + 1] = y2 - dG; \ - CLAMP(g[x_write + 1]); \ - b[x_write + 1] = y2 + dB; \ - CLAMP(b[x_write + 1]); \ - \ - x_write = (x_write + 2) & 7; \ - } \ +#define DECODE_YCbCr() \ + do { \ + int c; \ + \ + for (c = 0; c < 2; c++) { \ + uint8_t y1, y2; \ + int8_t Cr; \ + int8_t Cb; \ + int dR; \ + int dG; \ + int dB; \ + \ + y1 = src[0]; \ + Cr = src[1] - 0x80; \ + y2 = src[2]; \ + Cb = src[3] - 0x80; \ + src += 4; \ + \ + dR = (359 * Cr) >> 8; \ + dG = (88 * Cb + 183 * Cr) >> 8; \ + dB = (453 * Cb) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + x_write = (x_write + 2) & 7; \ + } \ } while (0) /*Both YUV formats are untested*/ -#define DECODE_YUV211() \ - do { \ - uint8_t y1, y2, y3, y4; \ - int8_t U, V; \ - int dR, dG, dB; \ - \ - U = src[0] - 0x80; \ - y1 = (298 * (src[1] - 16)) >> 8; \ - y2 = (298 * (src[2] - 16)) >> 8; \ - V = src[3] - 0x80; \ - y3 = (298 * (src[4] - 16)) >> 8; \ - y4 = (298 * (src[5] - 16)) >> 8; \ - src += 6; \ - \ - dR = (309 * V) >> 8; \ - dG = (100 * U + 208 * V) >> 8; \ - dB = (516 * U) >> 8; \ - \ - r[x_write] = y1 + dR; \ - CLAMP(r[x_write]); \ - g[x_write] = y1 - dG; \ - CLAMP(g[x_write]); \ - b[x_write] = y1 + dB; \ - CLAMP(b[x_write]); \ - \ - r[x_write + 1] = y2 + dR; \ - CLAMP(r[x_write + 1]); \ - g[x_write + 1] = y2 - dG; \ - CLAMP(g[x_write + 1]); \ - b[x_write + 1] = y2 + dB; \ - CLAMP(b[x_write + 1]); \ - \ - r[x_write + 2] = y3 + dR; \ - CLAMP(r[x_write + 2]); \ - g[x_write + 2] = y3 - dG; \ - CLAMP(g[x_write + 2]); \ - b[x_write + 2] = y3 + dB; \ - CLAMP(b[x_write + 2]); \ - \ - r[x_write + 3] = y4 + dR; \ - CLAMP(r[x_write + 3]); \ - g[x_write + 3] = y4 - dG; \ - CLAMP(g[x_write + 3]); \ - b[x_write + 3] = y4 + dB; \ - CLAMP(b[x_write + 3]); \ - \ - x_write = (x_write + 4) & 7; \ +#define DECODE_YUV211() \ + do { \ + uint8_t y1, y2, y3, y4; \ + int8_t U, V; \ + int dR; \ + int dG; \ + int dB; \ + \ + U = src[0] - 0x80; \ + y1 = (298 * (src[1] - 16)) >> 8; \ + y2 = (298 * (src[2] - 16)) >> 8; \ + V = src[3] - 0x80; \ + y3 = (298 * (src[4] - 16)) >> 8; \ + y4 = (298 * (src[5] - 16)) >> 8; \ + src += 6; \ + \ + dR = (309 * V) >> 8; \ + dG = (100 * U + 208 * V) >> 8; \ + dB = (516 * U) >> 8; \ + \ + r[x_write] = y1 + dR; \ + CLAMP(r[x_write]); \ + g[x_write] = y1 - dG; \ + CLAMP(g[x_write]); \ + b[x_write] = y1 + dB; \ + CLAMP(b[x_write]); \ + \ + r[x_write + 1] = y2 + dR; \ + CLAMP(r[x_write + 1]); \ + g[x_write + 1] = y2 - dG; \ + CLAMP(g[x_write + 1]); \ + b[x_write + 1] = y2 + dB; \ + CLAMP(b[x_write + 1]); \ + \ + r[x_write + 2] = y3 + dR; \ + CLAMP(r[x_write + 2]); \ + g[x_write + 2] = y3 - dG; \ + CLAMP(g[x_write + 2]); \ + b[x_write + 2] = y3 + dB; \ + CLAMP(b[x_write + 2]); \ + \ + r[x_write + 3] = y4 + dR; \ + CLAMP(r[x_write + 3]); \ + g[x_write + 3] = y4 - dG; \ + CLAMP(g[x_write + 3]); \ + b[x_write + 3] = y4 + dB; \ + CLAMP(b[x_write + 3]); \ + \ + x_write = (x_write + 4) & 7; \ } while (0) #define DECODE_YUV422() \ @@ -3830,13 +3844,17 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) int c; \ \ for (c = 0; c < 2; c++) { \ - uint8_t y1, y2; \ - int8_t U, V; \ - int dR, dG, dB; \ + uint8_t y1; \ + uint8_t y2; \ + int8_t U; \ + int8_t V; \ + int dR; \ + int dG; \ + int dB; \ \ - U = src[0] - 0x80; \ + U = src[0] - 0x80; \ y1 = (298 * (src[1] - 16)) >> 8; \ - V = src[2] - 0x80; \ + V = src[2] - 0x80; \ y2 = (298 * (src[3] - 16)) >> 8; \ src += 4; \ \ @@ -3862,128 +3880,149 @@ s3_virge_hwcursor_draw(svga_t *svga, int displine) } \ } while (0) -#define DECODE_RGB555() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - uint16_t dat; \ - \ - dat = *(uint16_t *) src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \ - b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_RGB555() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = \ + ((dat & 0x001f) << 3) | \ + ((dat & 0x001f) >> 2); \ + g[x_write + c] = \ + ((dat & 0x03e0) >> 2) | \ + ((dat & 0x03e0) >> 7); \ + b[x_write + c] = \ + ((dat & 0x7c00) >> 7) | \ + ((dat & 0x7c00) >> 12); \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define DECODE_RGB565() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - uint16_t dat; \ - \ - dat = *(uint16_t *) src; \ - src += 2; \ - \ - r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \ - g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \ - b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_RGB565() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + uint16_t dat; \ + \ + dat = *(uint16_t *)src; \ + src += 2; \ + \ + r[x_write + c] = \ + ((dat & 0x001f) << 3) | \ + ((dat & 0x001f) >> 2); \ + g[x_write + c] = \ + ((dat & 0x07e0) >> 3) | \ + ((dat & 0x07e0) >> 9); \ + b[x_write + c] = \ + ((dat & 0xf800) >> 8) | \ + ((dat & 0xf800) >> 13); \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define DECODE_RGB888() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 3; \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_RGB888() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 3; \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define DECODE_XRGB8888() \ - do { \ - int c; \ - \ - for (c = 0; c < 4; c++) { \ - r[x_write + c] = src[0]; \ - g[x_write + c] = src[1]; \ - b[x_write + c] = src[2]; \ - src += 4; \ - } \ - x_write = (x_write + 4) & 7; \ +#define DECODE_XRGB8888() \ + do { \ + int c; \ + \ + for (c = 0; c < 4; c++) { \ + r[x_write + c] = src[0]; \ + g[x_write + c] = src[1]; \ + b[x_write + c] = src[2]; \ + src += 4; \ + } \ + x_write = (x_write + 4) & 7; \ } while (0) -#define OVERLAY_SAMPLE() \ - do { \ - switch (virge->streams.sdif) { \ - case 1: \ - DECODE_YCbCr(); \ - break; \ - case 2: \ - DECODE_YUV422(); \ - break; \ - case 3: \ - DECODE_RGB555(); \ - break; \ - case 4: \ - DECODE_YUV211(); \ - break; \ - case 5: \ - DECODE_RGB565(); \ - break; \ - case 6: \ - DECODE_RGB888(); \ - break; \ - case 7: \ - default: \ - DECODE_XRGB8888(); \ - break; \ - } \ +#define OVERLAY_SAMPLE() \ + do { \ + switch (virge->streams.sdif) { \ + case 1: \ + DECODE_YCbCr(); \ + break; \ + case 2: \ + DECODE_YUV422(); \ + break; \ + case 3: \ + DECODE_RGB555(); \ + break; \ + case 4: \ + DECODE_YUV211(); \ + break; \ + case 5: \ + DECODE_RGB565(); \ + break; \ + case 6: \ + DECODE_RGB888(); \ + break; \ + case 7: \ + default: \ + DECODE_XRGB8888(); \ + break; \ + } \ } while (0) static void s3_virge_overlay_draw(svga_t *svga, int displine) { - const virge_t *virge = (virge_t *) svga->priv; - int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; - int h_acc = virge->streams.dda_horiz_accumulator; - int r[8]; - int g[8]; - int b[8]; - int x_size; - int x_read = 4; - int x_write = 4; - uint32_t *p; - uint8_t *src = &svga->vram[svga->overlay_latch.addr]; - - p = &(buffer32->line[displine][offset + svga->x_add]); - - if ((offset + virge->streams.sec_w) > virge->streams.pri_w) - x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; + virge_t *virge = (virge_t *) svga->priv; + int offset; + int r[8]; + int g[8]; + int b[8]; + int x_size; + int x_read = 4; + int x_write = 4; + int x; + uint32_t *p; + uint8_t *src = &svga->vram[svga->overlay_latch.addr]; + + if (virge->chip < S3_VIRGEGX2) + offset = (virge->streams.sec_x - virge->streams.pri_x) + 1; else + offset = virge->streams.sec_x + 1; + + p = &((uint32_t *)buffer32->line[displine])[offset + svga->x_add]; + + if (virge->chip < S3_VIRGEGX2) { + if ((offset + virge->streams.sec_w) > virge->streams.pri_w) + x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1; + else + x_size = virge->streams.sec_w + 1; + } else x_size = virge->streams.sec_w + 1; OVERLAY_SAMPLE(); - for (int x = 0; x < x_size; x++) { + for (x = 0; x < x_size; x++) { *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16); - h_acc += virge->streams.k1_horiz_scale; - if (h_acc >= 0) { + svga->overlay_latch.h_acc += virge->streams.k1_horiz_scale; + if (svga->overlay_latch.h_acc >= 0) { if ((x_read ^ (x_read + 1)) & ~3) OVERLAY_SAMPLE(); + x_read = (x_read + 1) & 7; - h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale); + svga->overlay_latch.h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale); } } @@ -4069,16 +4108,16 @@ s3_virge_pci_read(UNUSED(int func), int addr, void *priv) break; case 0x30: - ret = virge->pci_regs[0x30] & 0x01; + ret = (!virge->onboard) ? (virge->pci_regs[0x30] & 0x01) : 0x00; break; /*BIOS ROM address*/ case 0x31: ret = 0x00; break; case 0x32: - ret = virge->pci_regs[0x32]; + ret = (!virge->onboard) ? virge->pci_regs[0x32] : 0x00; break; case 0x33: - ret = virge->pci_regs[0x33]; + ret = (!virge->onboard) ? virge->pci_regs[0x33] : 0x00; break; case 0x34: @@ -4188,7 +4227,7 @@ s3_virge_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) s3_virge_updatemapping(virge); return; case 0x07: - virge->pci_regs[0x07] = val & 0x3e; + virge->pci_regs[0x07] &= ~(val & 0x30); return; case 0x0d: virge->pci_regs[0x0d] = val & 0xf8; @@ -4202,6 +4241,8 @@ s3_virge_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) case 0x30: case 0x32: case 0x33: + if (virge->onboard) + return; virge->pci_regs[addr] = val; if (virge->pci_regs[0x30] & 0x01) { uint32_t biosaddr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24); @@ -4245,113 +4286,53 @@ s3_virge_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv) } static void -s3_virge_reset(void *priv) +s3_virge_disable_handlers(virge_t *dev) { - virge_t *virge = (virge_t *) priv; - svga_t *svga = &virge->svga; - - memset(svga->crtc, 0x00, sizeof(svga->crtc)); - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = 1000ULL << 32; - svga->dispofftime = 1000ULL << 32; - svga->bpp = 8; - - io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - - memset(virge->pci_regs, 0x00, 256); - - virge->pci_regs[PCI_REG_COMMAND] = 3; - virge->pci_regs[0x05] = 0; - virge->pci_regs[0x06] = 0; - virge->pci_regs[0x07] = 2; - virge->pci_regs[0x32] = 0x0c; - virge->pci_regs[0x3d] = 1; - virge->pci_regs[0x3e] = 4; - virge->pci_regs[0x3f] = 0xff; - - switch (virge->local) { - case S3_VIRGE_325: - case S3_DIAMOND_STEALTH3D_2000: - virge->fifo_slots_num = 8; - virge->svga.crtc[0x59] = 0x70; - break; - case S3_DIAMOND_STEALTH3D_3000: - case S3_STB_VELOCITY_3D: - virge->fifo_slots_num = 8; - virge->svga.crtc[0x59] = 0x70; - break; - case S3_VIRGE_GX2: - case S3_DIAMOND_STEALTH3D_4000: - virge->fifo_slots_num = 16; - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - break; - - case S3_TRIO_3D2X: - virge->fifo_slots_num = 16; - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - break; - - default: - virge->fifo_slots_num = 8; - virge->svga.crtc[0x6c] = 1; - virge->svga.crtc[0x59] = 0x70; - break; - } - - if (virge->chip == S3_VIRGEGX2) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (1 << 5); - else { - switch (virge->memory_size) { - case 2: - if (virge->chip == S3_VIRGEVX) { - virge->svga.crtc[0x36] = (0 << 5); - } else - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5); - break; - case 8: - if (virge->chip == S3_TRIO3D2X) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (0 << 5); - else - virge->svga.crtc[0x36] = (3 << 5); - break; - case 4: - if (virge->chip == S3_VIRGEVX) - virge->svga.crtc[0x36] = (1 << 5); - else if (virge->chip == S3_TRIO3D2X) - virge->svga.crtc[0x36] = 2 | (2 << 2) | (1 << 4) | (2 << 5); - else - virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5); - break; + io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, + s3_virge_out, NULL, NULL, dev); + + mem_mapping_disable(&dev->linear_mapping); + mem_mapping_disable(&dev->mmio_mapping); + mem_mapping_disable(&dev->new_mmio_mapping); + mem_mapping_disable(&dev->svga.mapping); + mem_mapping_disable(&dev->bios_rom.mapping); + + /* Save all the mappings and the timers because they are part of linked lists. */ + reset_state->linear_mapping = dev->linear_mapping; + reset_state->mmio_mapping = dev->mmio_mapping; + reset_state->new_mmio_mapping = dev->new_mmio_mapping; + reset_state->svga.mapping = dev->svga.mapping; + reset_state->bios_rom.mapping = dev->bios_rom.mapping; + + reset_state->svga.timer = dev->svga.timer; + reset_state->svga.timer8514 = dev->svga.timer8514; +} - default: - break; - } - if (virge->local == S3_VIRGE_GX) - virge->svga.crtc[0x36] |= (1 << 2); +static void +s3_virge_reset(void *priv) +{ + virge_t *dev = (virge_t *) priv; + + if (reset_state != NULL) { + s3_virge_disable_handlers(dev); + dev->virge_busy = 0; + dev->fifo_write_idx = 0; + dev->fifo_read_idx = 0; + dev->s3d_busy = 0; + dev->s3d_write_idx = 0; + dev->s3d_read_idx = 0; + reset_state->pci_slot = dev->pci_slot; + + *dev = *reset_state; } - - virge->svga.crtc[0x37] = 1 | (7 << 5); - virge->svga.crtc[0x53] = 8; - - mem_mapping_disable(&virge->bios_rom.mapping); - - s3_virge_updatemapping(virge); - - mem_mapping_disable(&virge->mmio_mapping); - mem_mapping_disable(&virge->new_mmio_mapping); } static void * s3_virge_init(const device_t *info) { - const char *bios_fn; - virge_t *virge = malloc(sizeof(virge_t)); - - memset(virge, 0, sizeof(virge_t)); + const char *bios_fn = NULL; + virge_t *virge = (virge_t *) calloc(1, sizeof(virge_t)); + reset_state = calloc(1, sizeof(virge_t)); virge->bilinear_enabled = device_get_config_int("bilinear"); virge->dithering_enabled = device_get_config_int("dithering"); @@ -4360,13 +4341,18 @@ s3_virge_init(const device_t *info) else virge->memory_size = device_get_config_int("memory"); - switch (info->local) { + virge->onboard = !!(info->local & 0x100); + + if (!virge->onboard) switch (info->local) { case S3_VIRGE_325: bios_fn = ROM_VIRGE_325; break; case S3_DIAMOND_STEALTH3D_2000: bios_fn = ROM_DIAMOND_STEALTH3D_2000; break; + case S3_MIROCRYSTAL_3D: + bios_fn = ROM_MIROCRYSTAL_3D; + break; case S3_DIAMOND_STEALTH3D_3000: bios_fn = ROM_DIAMOND_STEALTH3D_3000; break; @@ -4408,11 +4394,12 @@ s3_virge_init(const device_t *info) rom_init(&virge->bios_rom, bios_fn, 0xc0000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); else rom_init(&virge->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - } - mem_mapping_disable(&virge->bios_rom.mapping); + mem_mapping_disable(&virge->bios_rom.mapping); + } - mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear, + mem_mapping_add(&virge->linear_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, @@ -4421,7 +4408,8 @@ s3_virge_init(const device_t *info) NULL, MEM_MAPPING_EXTERNAL, &virge->svga); - mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read, + mem_mapping_add(&virge->mmio_mapping, 0, 0, + s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, @@ -4430,7 +4418,8 @@ s3_virge_init(const device_t *info) NULL, MEM_MAPPING_EXTERNAL, virge); - mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read, + mem_mapping_add(&virge->new_mmio_mapping, 0, 0, + s3_virge_mmio_read, s3_virge_mmio_read_w, s3_virge_mmio_read_l, s3_virge_mmio_write, @@ -4442,7 +4431,7 @@ s3_virge_init(const device_t *info) io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge); - virge->pci_regs[PCI_REG_COMMAND] = 3; + virge->pci_regs[PCI_REG_COMMAND] = 7; virge->pci_regs[0x05] = 0; virge->pci_regs[0x06] = 0; virge->pci_regs[0x07] = 2; @@ -4458,6 +4447,7 @@ s3_virge_init(const device_t *info) switch (info->local) { case S3_VIRGE_325: case S3_DIAMOND_STEALTH3D_2000: + case S3_MIROCRYSTAL_3D: virge->fifo_slots_num = 8; virge->svga.decode_mask = (4 << 20) - 1; virge->virge_id_high = 0x56; @@ -4576,16 +4566,21 @@ s3_virge_init(const device_t *info) virge->svga.force_old_addr = 1; + virge->render_thread_run = 1; virge->wake_render_thread = thread_create_event(); - virge->wake_main_thread = thread_create_event(); - virge->not_full_event = thread_create_event(); - virge->render_thread_run = 1; - virge->render_thread = thread_create(render_thread, virge); + virge->wake_main_thread = thread_create_event(); + virge->not_full_event = thread_create_event(); + virge->render_thread = thread_create(render_thread, virge); - timer_add(&virge->tri_timer, s3_virge_tri_timer, virge, 0); + virge->fifo_thread_run = 1; + virge->wake_fifo_thread = thread_create_event(); + virge->fifo_not_full_event = thread_create_event(); + virge->fifo_thread = thread_create(fifo_thread, virge); virge->local = info->local; + *reset_state = *virge; + return virge; } @@ -4601,11 +4596,20 @@ s3_virge_close(void *priv) thread_destroy_event(virge->wake_main_thread); thread_destroy_event(virge->wake_render_thread); + virge->fifo_thread_run = 0; + thread_set_event(virge->wake_fifo_thread); + thread_wait(virge->fifo_thread); + thread_destroy_event(virge->fifo_not_full_event); + thread_destroy_event(virge->wake_fifo_thread); + svga_close(&virge->svga); ddc_close(virge->ddc); i2c_gpio_close(virge->i2c); + free(reset_state); + reset_state = NULL; + free(virge); } @@ -4621,6 +4625,12 @@ s3_virge_325_available(void) return rom_present(ROM_VIRGE_325); } +static int +s3_mirocrystal_3d_available(void) +{ + return rom_present(ROM_MIROCRYSTAL_3D); +} + static int s3_virge_988_diamond_available(void) { @@ -4840,6 +4850,20 @@ const device_t s3_virge_325_pci_device = { .config = s3_virge_config }; +const device_t s3_virge_325_onboard_pci_device = { + .name = "S3 ViRGE (325) On-Board PCI", + .internal_name = "virge325_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_VIRGE_325 | 0x100, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = NULL }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config +}; + const device_t s3_diamond_stealth_2000_pci_device = { .name = "S3 ViRGE (Diamond Stealth 3D 2000) PCI", .internal_name = "stealth3d_2000_pci", @@ -4854,6 +4878,20 @@ const device_t s3_diamond_stealth_2000_pci_device = { .config = s3_virge_config }; +const device_t s3_mirocrystal_3d_pci_device = { + .name = "S3 ViRGE (miroCRYSTAL 3D) PCI", + .internal_name = "mirocrystal_3d_pci", + .flags = DEVICE_PCI, + .local = S3_MIROCRYSTAL_3D, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = s3_mirocrystal_3d_available }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config +}; + const device_t s3_diamond_stealth_3000_pci_device = { .name = "S3 ViRGE/VX (Diamond Stealth 3D 3000) PCI", .internal_name = "stealth3d_3000_pci", @@ -4896,6 +4934,20 @@ const device_t s3_virge_375_pci_device = { .config = s3_virge_config }; +const device_t s3_virge_375_onboard_pci_device = { + .name = "S3 ViRGE/DX (375) On-Board PCI", + .internal_name = "virge375_onboard_pci", + .flags = DEVICE_PCI, + .local = S3_VIRGE_DX | 0x100, + .init = s3_virge_init, + .close = s3_virge_close, + .reset = s3_virge_reset, + { .available = NULL }, + .speed_changed = s3_virge_speed_changed, + .force_redraw = s3_virge_force_redraw, + .config = s3_virge_config +}; + const device_t s3_diamond_stealth_2000pro_pci_device = { .name = "S3 ViRGE/DX (Diamond Stealth 3D 2000 Pro) PCI", .internal_name = "stealth3d_2000pro_pci", diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 4632ab85e9..cecdcf8404 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -46,6 +46,7 @@ #include <86box/vid_xga_device.h> void svga_doblit(int wx, int wy, svga_t *svga); +void svga_poll(void *priv); svga_t *svga_8514; @@ -121,6 +122,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv) if (!dev && (addr >= 0x2ea) && (addr <= 0x2ed)) return; + if (addr >= 0x3c6 && addr <= 0x3c9) + svga_log("VGA OUT addr=%03x, val=%02x.\n", addr, val); + switch (addr) { case 0x2ea: dev->dac_mask = val; @@ -219,7 +223,8 @@ svga_out(uint16_t addr, uint8_t val, void *priv) xga->on = (val & 0x01) ? 0 : 1; if (ibm8514_active && dev) { dev->on[0] = (val & 0x01) ? 0 : 1; - dev->on[1] = dev->on[0]; + if (dev->local & 0xff) + dev->on[1] = dev->on[0]; } svga_log("3C3: VGA ON = %d.\n", val & 0x01); @@ -528,6 +533,9 @@ svga_in(uint16_t addr, void *priv) break; } + if ((addr >= 0x3c6) && (addr <= 0x3c9)) + svga_log("VGA IN addr=%03x, temp=%02x.\n", addr, ret); + return ret; } @@ -551,11 +559,12 @@ svga_set_ramdac_type(svga_t *svga, int type) } if (xga_active && xga) { if (svga->ramdac_type == RAMDAC_8BIT) - xga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); - else - xga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, - (svga->vgapal[c].g & 0x3f) * 4, - (svga->vgapal[c].b & 0x3f) * 4); + xga->pallook[c] = makecol32(xga->xgapal[c].r, xga->xgapal[c].g, xga->xgapal[c].b); + else { + xga->pallook[c] = makecol32((xga->xgapal[c].r & 0x3f) * 4, + (xga->xgapal[c].g & 0x3f) * 4, + (xga->xgapal[c].b & 0x3f) * 4); + } } if (svga->ramdac_type == RAMDAC_8BIT) svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); @@ -661,11 +670,11 @@ svga_recalctimings(svga_t *svga) } if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) { /*40 column*/ + if (svga->seqregs[1] & 8) { /*40 column*/ svga->render = svga_render_text_40; - } else { + } else svga->render = svga_render_text_80; - } + svga->hdisp_old = svga->hdisp; } else { svga->hdisp_old = svga->hdisp; @@ -677,9 +686,10 @@ svga_recalctimings(svga_t *svga) else svga->render = svga_render_4bpp_highres; } else if ((svga->gdcreg[5] & 0x60) == 0x20) { - if (svga->seqregs[1] & 8) /*Low res (320)*/ + if (svga->seqregs[1] & 8) { /*Low res (320)*/ svga->render = svga_render_2bpp_lowres; - else + svga_log("2 bpp low res\n"); + } else svga->render = svga_render_2bpp_highres; } else { svga->map8 = svga->pallook; @@ -850,8 +860,10 @@ svga_recalctimings(svga_t *svga) svga->y_add = (svga->monitor->mon_overscan_y >> 1); svga->x_add = (svga->monitor->mon_overscan_x >> 1); - if (svga->vblankstart < svga->dispend) + if (svga->vblankstart < svga->dispend) { + svga_log("DISPEND > VBLANKSTART.\n"); svga->dispend = svga->vblankstart; + } crtcconst = svga->clock * svga->char_width; if (ibm8514_active && (svga->dev8514 != NULL)) { @@ -935,11 +947,11 @@ svga_recalctimings(svga_t *svga) if (dev->dispofftime < TIMER_USEC) dev->dispofftime = TIMER_USEC; - timer_disable(&svga->timer); - timer_set_delay_u64(&svga->timer8514, TIMER_USEC); + svga_log("IBM 8514/A poll.\n"); + timer_set_callback(&svga->timer, ibm8514_poll); } else { - timer_disable(&svga->timer8514); - timer_set_delay_u64(&svga->timer, TIMER_USEC); + svga_log("SVGA Poll.\n"); + timer_set_callback(&svga->timer, svga_poll); } } @@ -1025,7 +1037,7 @@ svga_poll(void *priv) if (!svga->override) { if (xga_active && xga && xga->on) { if ((xga->disp_cntl_2 & 7) >= 2) { - xga_poll(xga, svga); + xga_poll(svga); return; } } @@ -1213,9 +1225,11 @@ svga_poll(void *priv) if (!svga->override) { if (svga->vertical_linedbl) { wy = (svga->lastline - svga->firstline) << 1; + svga->vdisp = wy + 1; svga_doblit(wx, wy, svga); } else { wy = svga->lastline - svga->firstline; + svga->vdisp = wy + 1; svga_doblit(wx, wy, svga); } } @@ -1332,11 +1346,11 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize, svga->dispontime = 1000ULL << 32; svga->dispofftime = 1000ULL << 32; svga->bpp = 8; - svga->vram = calloc(memsize, 1); + svga->vram = calloc(memsize + 8, 1); svga->vram_max = memsize; svga->vram_display_mask = svga->vram_mask = memsize - 1; svga->decode_mask = 0x7fffff; - svga->changedvram = calloc(memsize >> 12, 1); + svga->changedvram = calloc((memsize >> 12) + 1, 1); svga->recalctimings_ex = recalctimings_ex; svga->video_in = video_in; svga->video_out = video_out; @@ -1394,7 +1408,7 @@ svga_close(svga_t *svga) svga_pri = NULL; } -static uint32_t +uint32_t svga_decode_addr(svga_t *svga, uint32_t addr, int write) { int memory_map_mode = (svga->gdcreg[6] >> 2) & 3; @@ -1435,7 +1449,6 @@ static __inline void svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; int writemask2 = svga->writemask; int reset_wm = 0; latch_t vall; @@ -1449,40 +1462,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_write_b; if (!linear) { - if (xga_active && xga) { - if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { - if (val == 0xa5) { /*Memory size test of XGA*/ - xga->test = val; - if (addr == 0xa0001) - xga->a5_test = 1; - else if (addr == 0xafffe) - xga->a5_test = 2; - - xga->on = 0; - vga_on = 1; - xga->disp_cntl_2 = 0; - svga_log("XGA test1 addr = %05x.\n", addr); - return; - } else if (val == 0x5a) { - xga->test = val; - xga->on = 0; - vga_on = 1; - xga->disp_cntl_2 = 0; - svga_log("XGA test2 addr = %05x.\n", addr); - return; - } else if ((addr == 0xa0000) || (addr == 0xa0010)) { - addr += xga->write_bank; - xga->vram[addr & xga->vram_mask] = val; - svga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x.\n", val, addr, svga->banked_mask); - if (!xga->a5_test) - xga->linear_endian_reverse = 1; - return; - } - } else { - xga->on = 0; - vga_on = 1; - } - } + xga_write_test(addr, val, svga); addr = svga_decode_addr(svga, addr, 1); if (addr == 0xffffffff) @@ -1657,12 +1637,11 @@ static __inline uint8_t svga_read_common(uint32_t addr, uint8_t linear, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint32_t latch_addr = 0; int readplane = svga->readplane; uint8_t count; uint8_t temp; - uint8_t ret; + uint8_t ret = 0x00; if (svga->adv_flags & FLAG_ADDR_BY8) readplane = svga->gdcreg[4] & 7; @@ -1670,39 +1649,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *priv) cycles -= svga->monitor->mon_video_timing_read_b; if (!linear) { - if (xga_active && xga) { - if (((xga->op_mode & 7) >= 4) && (xga->aperture_cntl >= 1)) { - if (xga->test == 0xa5) { /*Memory size test of XGA*/ - if (addr == 0xa0001) { - ret = xga->test; - xga->on = 1; - vga_on = 0; - } else if ((addr == 0xa0000) && (xga->a5_test == 1)) { /*This is required by XGAKIT to pass the memory test*/ - svga_log("A5 test bank = %x.\n", addr); - addr += xga->read_bank; - ret = xga->vram[addr & xga->vram_mask]; - } else { - ret = xga->test; - xga->on = 1; - vga_on = 0; - } - svga_log("A5 read: XGA ON = %d, addr = %05x, ret = %02x, test1 = %x.\n", xga->on, addr, ret, xga->a5_test); - return ret; - } else if (xga->test == 0x5a) { - ret = xga->test; - xga->on = 1; - vga_on = 0; - svga_log("5A read: XGA ON = %d.\n", xga->on); - return ret; - } else if ((addr == 0xa0000) || (addr == 0xa0010)) { - addr += xga->read_bank; - return xga->vram[addr & xga->vram_mask]; - } - } else { - xga->on = 0; - vga_on = 1; - } - } + (void) xga_read_test(addr, svga); addr = svga_decode_addr(svga, addr, 0); if (addr == 0xffffffff) diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 9b395ea6cb..c05d308fa3 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -178,14 +178,14 @@ svga_render_text_40(svga_t *svga) charaddr = svga->charseta + (chr * 128); if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; + bg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + fg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; + fg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + bg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + bg = svga->pallook[svga->egapal[(attr >> 4) & 7] & svga->dac_mask]; if (svga->blink & 16) fg = bg; } @@ -256,13 +256,13 @@ svga_render_text_80(svga_t *svga) charaddr = svga->charseta + (chr * 128); if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; + bg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + fg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; + fg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + bg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + bg = svga->pallook[svga->egapal[(attr >> 4) & 7] & svga->dac_mask]; if (svga->blink & 16) fg = bg; } @@ -323,13 +323,13 @@ svga_render_text_80_ksc5601(svga_t *svga) attr = svga->vram[addr + 1]; if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; + bg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + fg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; + fg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + bg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + bg = svga->pallook[svga->egapal[(attr >> 4) & 7] & svga->dac_mask]; if (svga->blink & 16) fg = bg; } @@ -378,13 +378,13 @@ svga_render_text_80_ksc5601(svga_t *svga) attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; if (drawcursor) { - bg = svga->pallook[svga->egapal[attr & 15]]; - fg = svga->pallook[svga->egapal[attr >> 4]]; + bg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + fg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; } else { - fg = svga->pallook[svga->egapal[attr & 15]]; - bg = svga->pallook[svga->egapal[attr >> 4]]; + fg = svga->pallook[svga->egapal[attr & 15] & svga->dac_mask]; + bg = svga->pallook[svga->egapal[attr >> 4] & svga->dac_mask]; if (attr & 0x80 && svga->attrregs[0x10] & 8) { - bg = svga->pallook[svga->egapal[(attr >> 4) & 7]]; + bg = svga->pallook[svga->egapal[(attr >> 4) & 7] & svga->dac_mask]; if (svga->blink & 16) fg = bg; } @@ -418,6 +418,202 @@ svga_render_text_80_ksc5601(svga_t *svga) } } +void +svga_render_2bpp_s3_lowres(svga_t *svga) +{ + int changed_offset; + int x; + uint8_t dat[2]; + uint32_t addr; + uint32_t *p; + uint32_t changed_addr; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->force_old_addr) { + changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { + addr = svga->ma; + + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; + addr &= ~7; + + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; + + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } + + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + svga->ma &= svga->vram_mask; + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3] & svga->dac_mask]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3] & svga->dac_mask]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3] & svga->dac_mask]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3] & svga->dac_mask]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3] & svga->dac_mask]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3] & svga->dac_mask]; + p += 16; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 16) { + addr = svga->remap_func(svga, svga->ma); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + + svga->ma &= svga->vram_mask; + + p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; + p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; + p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3] & svga->dac_mask]; + p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3] & svga->dac_mask]; + p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3] & svga->dac_mask]; + p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3] & svga->dac_mask]; + p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3] & svga->dac_mask]; + p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3] & svga->dac_mask]; + + p += 16; + } + } + } +} + +void +svga_render_2bpp_s3_highres(svga_t *svga) +{ + int changed_offset; + int x; + uint8_t dat[2]; + uint32_t addr; + uint32_t *p; + uint32_t changed_addr; + + if ((svga->displine + svga->y_add) < 0) + return; + + if (svga->force_old_addr) { + changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + + if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->ma; + + if (!(svga->crtc[0x17] & 0x40)) { + addr = (addr << 1) & svga->vram_mask; + addr &= ~7; + + if ((svga->crtc[0x17] & 0x20) && (svga->ma & 0x20000)) + addr |= 4; + + if (!(svga->crtc[0x17] & 0x20) && (svga->ma & 0x8000)) + addr |= 4; + } + + if (!(svga->crtc[0x17] & 0x01)) + addr = (addr & ~0x8000) | ((svga->sc & 1) ? 0x8000 : 0); + + if (!(svga->crtc[0x17] & 0x02)) + addr = (addr & ~0x10000) | ((svga->sc & 2) ? 0x10000 : 0); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + svga->ma &= svga->vram_mask; + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3] & svga->dac_mask]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3] & svga->dac_mask]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3] & svga->dac_mask]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3] & svga->dac_mask]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3] & svga->dac_mask]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3] & svga->dac_mask]; + p += 8; + } + } + } else { + changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + p = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add]; + + if (svga->firstline_draw == 2000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; + + for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { + addr = svga->remap_func(svga, svga->ma); + + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr | 0x1]; + if (svga->seqregs[1] & 4) + svga->ma += 2; + else + svga->ma += 4; + + svga->ma &= svga->vram_mask; + + p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3] & svga->dac_mask]; + p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3] & svga->dac_mask]; + p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3] & svga->dac_mask]; + p[3] = svga->pallook[svga->egapal[dat[0] & 3] & svga->dac_mask]; + p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3] & svga->dac_mask]; + p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3] & svga->dac_mask]; + p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3] & svga->dac_mask]; + p[7] = svga->pallook[svga->egapal[dat[1] & 3] & svga->dac_mask]; + + p += 8; + } + } + } +} + void svga_render_2bpp_headland_highres(svga_t *svga) { @@ -456,17 +652,17 @@ svga_render_2bpp_headland_highres(svga_t *svga) svga->ma &= svga->vram_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask] & svga->dac_mask]; + p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask] & svga->dac_mask]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask] & svga->dac_mask]; + p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask] & svga->dac_mask]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask] & svga->dac_mask]; + p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask] & svga->dac_mask]; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask] & svga->dac_mask]; + p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask] & svga->dac_mask]; p += 8; } @@ -672,8 +868,8 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) } } else if (combine8bits) { if (svga->packed_4bpp) { - uint32_t p0 = svga->map8[c0]; - uint32_t p1 = svga->map8[c1]; + uint32_t p0 = svga->map8[c0 & svga->dac_mask]; + uint32_t p1 = svga->map8[c1 & svga->dac_mask]; const int outoffs = i << dwshift; for (int subx = 0; subx < dotwidth; subx++) p[outoffs + subx] = p0; @@ -681,14 +877,14 @@ svga_render_indexed_gfx(svga_t *svga, bool highres, bool combine8bits) p[outoffs + subx + dotwidth] = p1; } else { uint32_t ccombined = (c0 << 4) | c1; - uint32_t p0 = svga->map8[ccombined]; + uint32_t p0 = svga->map8[ccombined & svga->dac_mask]; const int outoffs = (i >> 1) << dwshift; for (int subx = 0; subx < dotwidth; subx++) p[outoffs + subx] = p0; } } else { - uint32_t p0 = svga->pallook[svga->egapal[c0]]; - uint32_t p1 = svga->pallook[svga->egapal[c1]]; + uint32_t p0 = svga->pallook[svga->egapal[c0] & svga->dac_mask]; + uint32_t p1 = svga->pallook[svga->egapal[c1] & svga->dac_mask]; const int outoffs = i << dwshift; for (int subx = 0; subx < dotwidth; subx++) p[outoffs + subx] = p0; @@ -738,16 +934,16 @@ svga_render_8bpp_clone_highres(svga_t *svga) for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; + p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->map8[dat & 0xff]; - p[5] = svga->map8[(dat >> 8) & 0xff]; - p[6] = svga->map8[(dat >> 16) & 0xff]; - p[7] = svga->map8[(dat >> 24) & 0xff]; + p[4] = svga->map8[dat & svga->dac_mask & 0xff]; + p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 8; p += 8; @@ -767,16 +963,16 @@ svga_render_8bpp_clone_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; + p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->map8[dat & 0xff]; - p[5] = svga->map8[(dat >> 8) & 0xff]; - p[6] = svga->map8[(dat >> 16) & 0xff]; - p[7] = svga->map8[(dat >> 24) & 0xff]; + p[4] = svga->map8[dat & svga->dac_mask & 0xff]; + p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 8; p += 8; @@ -785,10 +981,10 @@ svga_render_8bpp_clone_highres(svga_t *svga) for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 4) { addr = svga->remap_func(svga, svga->ma); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; + p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 4; p += 4; @@ -847,10 +1043,10 @@ svga_render_8bpp_lowres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = p[1] = svga->map8[dat & 0xff]; - p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; - p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; - p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + p[0] = p[1] = svga->map8[dat & svga->dac_mask & 0xff]; + p[2] = p[3] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[4] = p[5] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[6] = p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 4; p += 8; @@ -859,10 +1055,10 @@ svga_render_8bpp_lowres(svga_t *svga) for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) { addr = svga->remap_func(svga, svga->ma); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - p[0] = p[1] = svga->map8[dat & 0xff]; - p[2] = p[3] = svga->map8[(dat >> 8) & 0xff]; - p[4] = p[5] = svga->map8[(dat >> 16) & 0xff]; - p[6] = p[7] = svga->map8[(dat >> 24) & 0xff]; + p[0] = p[1] = svga->map8[dat & svga->dac_mask & 0xff]; + p[2] = p[3] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[4] = p[5] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[6] = p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 4; p += 8; @@ -895,16 +1091,16 @@ svga_render_8bpp_highres(svga_t *svga) for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; + p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->map8[dat & 0xff]; - p[5] = svga->map8[(dat >> 8) & 0xff]; - p[6] = svga->map8[(dat >> 16) & 0xff]; - p[7] = svga->map8[(dat >> 24) & 0xff]; + p[4] = svga->map8[dat & svga->dac_mask & 0xff]; + p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 8; p += 8; @@ -924,16 +1120,16 @@ svga_render_8bpp_highres(svga_t *svga) if (!svga->remap_required) { for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 8) { dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; + p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->map8[dat & 0xff]; - p[5] = svga->map8[(dat >> 8) & 0xff]; - p[6] = svga->map8[(dat >> 16) & 0xff]; - p[7] = svga->map8[(dat >> 24) & 0xff]; + p[4] = svga->map8[dat & svga->dac_mask & 0xff]; + p[5] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[6] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[7] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 8; p += 8; @@ -942,10 +1138,10 @@ svga_render_8bpp_highres(svga_t *svga) for (x = 0; x <= (svga->hdisp /* + svga->scrollcache*/); x += 4) { addr = svga->remap_func(svga, svga->ma); dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]); - p[0] = svga->map8[dat & 0xff]; - p[1] = svga->map8[(dat >> 8) & 0xff]; - p[2] = svga->map8[(dat >> 16) & 0xff]; - p[3] = svga->map8[(dat >> 24) & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; + p[1] = svga->map8[(dat >> 8) & svga->dac_mask & 0xff]; + p[2] = svga->map8[(dat >> 16) & svga->dac_mask & 0xff]; + p[3] = svga->map8[(dat >> 24) & svga->dac_mask & 0xff]; svga->ma += 4; p += 4; @@ -977,19 +1173,19 @@ svga_render_8bpp_tseng_lowres(svga_t *svga) dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[0] = p[1] = svga->map8[dat & 0xff]; + p[0] = p[1] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[2] = p[3] = svga->map8[dat & 0xff]; + p[2] = p[3] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[4] = p[5] = svga->map8[dat & 0xff]; + p[4] = p[5] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[6] = p[7] = svga->map8[dat & 0xff]; + p[6] = p[7] = svga->map8[dat & svga->dac_mask & 0xff]; svga->ma += 4; p += 8; @@ -1018,36 +1214,36 @@ svga_render_8bpp_tseng_highres(svga_t *svga) dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]); if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[0] = svga->map8[dat & 0xff]; + p[0] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[1] = svga->map8[dat & 0xff]; + p[1] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[2] = svga->map8[dat & 0xff]; + p[2] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[3] = svga->map8[dat & 0xff]; + p[3] = svga->map8[dat & svga->dac_mask & 0xff]; dat = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[4] = svga->map8[dat & 0xff]; + p[4] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[5] = svga->map8[dat & 0xff]; + p[5] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[6] = svga->map8[dat & 0xff]; + p[6] = svga->map8[dat & svga->dac_mask & 0xff]; dat >>= 8; if (svga->attrregs[0x10] & 0x80) dat = (dat & ~0xf0) | ((svga->attrregs[0x14] & 0x0f) << 4); - p[7] = svga->map8[dat & 0xff]; + p[7] = svga->map8[dat & svga->dac_mask & 0xff]; svga->ma += 8; p += 8; diff --git a/src/video/vid_table.c b/src/video/vid_table.c index b2686b2f31..8597123573 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -47,38 +47,11 @@ static video_timings_t timing_default = { .type = VIDEO_ISA, .write_b = 8, .writ static int was_reset = 0; -static const device_t vid_none_device = { - .name = "None", - .internal_name = "none", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; -static const device_t vid_internal_device = { - .name = "Internal", - .internal_name = "internal", - .flags = 0, - .local = 0, - .init = NULL, - .close = NULL, - .reset = NULL, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - static const VIDEO_CARD video_cards[] = { // clang-format off - { &vid_none_device }, - { &vid_internal_device }, + { &device_none }, + { &device_internal }, { &atiega800p_device }, { &mach8_vga_isa_device, VIDEO_FLAG_TYPE_8514 }, { &mach32_isa_device, VIDEO_FLAG_TYPE_8514 }, @@ -87,9 +60,10 @@ video_cards[] = { { &ati18800_vga88_device }, { &ati28800_device }, { &compaq_ati28800_device }, -#if defined(DEV_BRANCH) && defined(USE_XL24) + { &ati28800_wonder1024d_xl_plus_device }, +#ifdef USE_XL24 { &ati28800_wonderxl24_device }, -#endif +#endif /* USE_XL24 */ { &ati18800_device }, { &ati18800_wonder_device }, { &cga_device }, @@ -188,6 +162,7 @@ video_cards[] = { { &s3_diamond_stealth64_pci_device }, { &s3_9fx_pci_device }, { &s3_phoenix_trio64_pci_device }, + { &s3_diamond_stealth64_968_pci_device }, { &s3_elsa_winner2000_pro_x_pci_device }, { &s3_mirovideo_40sv_ergo_968_pci_device }, { &s3_9fx_771_pci_device }, @@ -200,6 +175,7 @@ video_cards[] = { { &s3_trio64v2_dx_pci_device }, { &s3_virge_325_pci_device }, { &s3_diamond_stealth_2000_pci_device }, + { &s3_mirocrystal_3d_pci_device }, { &s3_diamond_stealth_3000_pci_device }, { &s3_stb_velocity_3d_pci_device }, { &s3_virge_375_pci_device }, @@ -252,8 +228,7 @@ video_cards[] = { { &s3_9fx_vlb_device }, { &s3_phoenix_trio64_vlb_device }, { &s3_spea_mirage_p64_vlb_device }, - { &s3_phoenix_vision968_vlb_device }, - { &s3_phoenix_vision868_vlb_device }, + { &s3_diamond_stealth64_968_vlb_device }, { &s3_stb_powergraph_64_video_vlb_device }, { &ht216_32_standalone_device }, { &tgui9400cxi_device }, @@ -261,7 +236,9 @@ video_cards[] = { { &s3_virge_357_agp_device }, { &s3_diamond_stealth_4000_agp_device }, { &s3_trio3d2x_agp_device }, +#ifdef USE_G100 { &productiva_g100_device, VIDEO_FLAG_TYPE_SPECIAL }, +#endif /*USE_G100 */ { &velocity_100_agp_device }, { &velocity_200_agp_device }, { &voodoo_3_1000_agp_device }, @@ -349,12 +326,14 @@ video_reset(int card) monitor_index_global = 0; loadfont("roms/video/mda/mda.rom", 0); - if ((card != VID_NONE) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY) && - (gfxcard[1] > VID_INTERNAL) && device_is_valid(video_card_getdevice(gfxcard[1]), machine)) { - video_monitor_init(1); - monitor_index_global = 1; - device_add(video_cards[gfxcard[1]].device); - monitor_index_global = 0; + for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { + if ((card != VID_NONE) && !machine_has_flags(machine, MACHINE_VIDEO_ONLY) && + (gfxcard[i] > VID_INTERNAL) && device_is_valid(video_card_getdevice(gfxcard[i]), machine)) { + video_monitor_init(i); + monitor_index_global = 1; + device_add(video_cards[gfxcard[i]].device); + monitor_index_global = 0; + } } /* Do not initialize internal cards here. */ diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index 490c724cea..9ec7e61051 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -145,12 +145,11 @@ typedef struct tgui_t { uint32_t pattern_32[8 * 8]; } accel; - uint8_t ext_gdc_regs[16]; /*TGUI9400CXi only*/ - uint8_t copy_latch[16]; + uint8_t copy_latch[16]; /*TGUI9400CXi only*/ uint8_t tgui_3d8, tgui_3d9; int oldmode; - uint8_t oldctrl1, newctrl1; + uint8_t oldctrl1; uint8_t oldctrl2, newctrl2; uint8_t oldgr0e, newgr0e; @@ -160,6 +159,7 @@ typedef struct tgui_t { int ramdac_state; uint8_t ramdac_ctrl; + uint8_t alt_clock; int clock_m, clock_n, clock_k; @@ -212,9 +212,6 @@ static void tgui_ext_writel(uint32_t addr, uint32_t val, void *priv); static __inline uint32_t dword_remap(svga_t *svga, uint32_t in_addr) { - if (svga->packed_chain4) - return in_addr; - return ((in_addr << 2) & 0x3fff0) | ((in_addr >> 14) & 0xc) | (in_addr & ~0x3fffc); } @@ -297,7 +294,7 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) { tgui_t *tgui = (tgui_t *) priv; svga_t *svga = &tgui->svga; - uint8_t old; + uint8_t old, o; if (((addr & 0xFFF0) == 0x3D0 || (addr & 0xFFF0) == 0x3B0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -331,6 +328,15 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) svga->read_bank = svga->write_bank; return; + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + svga->seqregs[svga->seqaddr] = val; + return; + default: break; } @@ -344,20 +350,7 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) if (tgui->ramdac_state == 4) { tgui->ramdac_state = 0; tgui->ramdac_ctrl = val; - switch ((tgui->ramdac_ctrl >> 4) & 0x0f) { - case 1: - svga->bpp = 15; - break; - case 3: - svga->bpp = 16; - break; - case 0x0d: - svga->bpp = (tgui->type >= TGUI_9660) ? 32 : 24; - break; - default: - svga->bpp = 8; - break; - } + //pclog("TGUI ramdac ctrl=%02x.\n", (tgui->ramdac_ctrl >> 4) & 0x0f); svga_recalctimings(svga); return; } @@ -374,30 +367,35 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) break; case 0x3CF: - if (svga->gdcaddr == 0x23) { - svga->dpms = !!(val & 0x03); - svga_recalctimings(svga); - } - if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) { - old = tgui->ext_gdc_regs[svga->gdcaddr & 15]; - tgui->ext_gdc_regs[svga->gdcaddr & 15] = val; - if (svga->gdcaddr == 16) - tgui_recalcmapping(tgui); - return; - } + o = svga->gdcreg[svga->gdcaddr]; switch (svga->gdcaddr) { - case 0x6: + case 2: + svga->colourcompare = val; + break; + case 4: + svga->readplane = val & 3; + break; + case 5: + svga->writemode = val & 3; + svga->readmode = val & 8; + svga->chain2_read = val & 0x10; + break; + case 6: if (svga->gdcreg[6] != val) { svga->gdcreg[6] = val; tgui_recalcmapping(tgui); } - return; + break; + case 7: + svga->colournocare = val; + break; case 0x0e: svga->gdcreg[0xe] = val ^ 2; if ((svga->gdcreg[0xf] & 1) == 1) svga->read_bank = (svga->gdcreg[0xe]) * 65536; break; + case 0x0f: if (val & 1) svga->read_bank = (svga->gdcreg[0xe]) * 65536; @@ -414,6 +412,12 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) svga->write_bank = (svga->seqregs[0xe]) * 65536; break; + case 0x23: + svga->dpms = !!(val & 0x03); + svga_recalctimings(svga); + break; + + case 0x2f: case 0x5a: case 0x5b: case 0x5c: @@ -426,11 +430,36 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) default: break; } - break; + svga->gdcreg[svga->gdcaddr] = val; + + if (tgui->type == TGUI_9400CXI) { + if ((svga->gdcaddr >= 0x10) && (svga->gdcaddr <= 0x1f)) { + tgui_recalcmapping(tgui); + return; + } + } + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only); + if (((svga->gdcaddr == 5) && ((val ^ o) & 0x70)) || ((svga->gdcaddr == 6) && ((val ^ o) & 1))) + svga_recalctimings(svga); + return; case 0x3D4: svga->crtcreg = val; return; case 0x3D5: + if (!(svga->seqregs[0x0e] & 0x80) && !tgui->oldmode) { + switch (svga->crtcreg) { + case 0x21: + case 0x29: + case 0x2a: + case 0x38: + case 0x39: + case 0x3b: + case 0x3c: + return; + default: + break; + } + } if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80)) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) @@ -482,8 +511,12 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) svga->hwcursor.y = (svga->crtc[0x42] | (svga->crtc[0x43] << 8)) & 0x7ff; if ((tgui->accel.ger22 & 0xff) == 8) { - if (svga->bpp != 24) + if (svga->bpp != 24) { svga->hwcursor.x <<= 1; + svga_recalctimings(svga); + if ((svga->vdisp == 1022) && svga->interlace) + svga->hwcursor.x >>= 1; + } } svga->hwcursor.xoff = svga->crtc[0x46] & 0x3f; @@ -531,6 +564,10 @@ tgui_out(uint16_t addr, uint8_t val, void *priv) svga->read_bank = (val & 0x3f) * 65536; return; + case 0x3DB: + tgui->alt_clock = val & 0xe3; + return; + case 0x43c8: tgui->clock_n = val & 0x7f; tgui->clock_m = (tgui->clock_m & ~1) | (val >> 7); @@ -591,6 +628,8 @@ tgui_in(uint16_t addr, void *priv) return tgui->oldctrl1 | 0x88; return svga->seqregs[0x0e]; } + if ((svga->seqaddr >= 0x5a) && (svga->seqaddr <= 0x5f)) + return svga->seqregs[svga->seqaddr]; break; case 0x3C6: @@ -610,10 +649,10 @@ tgui_in(uint16_t addr, void *priv) break; case 0x3CF: - if (tgui->type == TGUI_9400CXI && svga->gdcaddr >= 16 && svga->gdcaddr < 32) - return tgui->ext_gdc_regs[svga->gdcaddr & 15]; if (svga->gdcaddr >= 0x5a && svga->gdcaddr <= 0x5f) return svga->gdcreg[svga->gdcaddr]; + if (svga->gdcaddr == 0x2f) + return svga->gdcreg[svga->gdcaddr]; break; case 0x3D4: return svga->crtcreg; @@ -636,6 +675,8 @@ tgui_in(uint16_t addr, void *priv) return tgui->tgui_3d8; case 0x3d9: return tgui->tgui_3d9; + case 0x3db: + return tgui->alt_clock; default: break; @@ -650,28 +691,49 @@ tgui_recalctimings(svga_t *svga) uint8_t ger22lower = (tgui->accel.ger22 & 0xff); uint8_t ger22upper = (tgui->accel.ger22 >> 8); - if (!svga->rowoffset) - svga->rowoffset = 0x100; + if (tgui->type >= TGUI_9440) { + if ((svga->crtc[0x38] & 0x19) == 0x09) + svga->bpp = 32; + else { + switch ((tgui->ramdac_ctrl >> 4) & 0x0f) { + case 0x01: + svga->bpp = 15; + break; + case 0x03: + svga->bpp = 16; + break; + case 0x0d: + svga->bpp = 24; + break; + default: + svga->bpp = 8; + break; + } + } + } + + if ((tgui->type >= TGUI_9440) && (svga->bpp >= 24)) + svga->hdisp = (svga->crtc[1] + 1) << 3; - if (svga->crtc[0x29] & 0x10) + if (((svga->crtc[0x29] & 0x30) && (svga->bpp >= 15)) || !svga->rowoffset) svga->rowoffset |= 0x100; - if ((tgui->type >= TGUI_9440) && (svga->bpp >= 24)) - svga->hdisp = (svga->crtc[1] + 1) * 8; + //pclog("BPP=%d, DataWidth=%02x, CRTC29 bit 4-5=%02x, pixbusmode=%02x, rowoffset=%02x, doublerowoffset=%x.\n", svga->bpp, svga->crtc[0x2a] & 0x40, svga->crtc[0x29] & 0x30, svga->crtc[0x38], svga->rowoffset, svga->gdcreg[0x2f] & 4); if ((svga->crtc[0x1e] & 0xA0) == 0xA0) svga->ma_latch |= 0x10000; - if ((svga->crtc[0x27] & 0x01) == 0x01) + if (svga->crtc[0x27] & 0x01) svga->ma_latch |= 0x20000; - if ((svga->crtc[0x27] & 0x02) == 0x02) + if (svga->crtc[0x27] & 0x02) svga->ma_latch |= 0x40000; - if ((svga->crtc[0x27] & 0x04) == 0x04) + if (svga->crtc[0x27] & 0x04) svga->ma_latch |= 0x80000; if (svga->crtc[0x27] & 0x08) svga->split |= 0x400; if (svga->crtc[0x27] & 0x10) svga->dispend |= 0x400; + if (svga->crtc[0x27] & 0x20) svga->vsyncstart |= 0x400; if (svga->crtc[0x27] & 0x40) @@ -684,15 +746,18 @@ tgui_recalctimings(svga_t *svga) svga->lowres = 0; } + svga->interlace = !!(svga->crtc[0x1e] & 4); + if (svga->interlace && (tgui->type < TGUI_9440)) + svga->rowoffset >>= 1; + + if (svga->vdisp == 1020) + svga->vdisp += 2; + if ((tgui->oldctrl2 & 0x10) || (svga->crtc[0x2a] & 0x40)) svga->ma_latch <<= 1; svga->lowres = !(svga->crtc[0x2a] & 0x40); - svga->interlace = !!(svga->crtc[0x1e] & 4); - if (svga->interlace && (tgui->type < TGUI_9440)) - svga->rowoffset >>= 1; - if (tgui->type >= TGUI_9440) { if (svga->miscout & 8) svga->clock = (cpuclock * (double) (1ULL << 32)) / (((tgui->clock_n + 8) * 14318180.0) / ((tgui->clock_m + 2) * (1 << tgui->clock_k))); @@ -749,6 +814,7 @@ tgui_recalctimings(svga_t *svga) default: break; } + if (svga->gdcreg[0xf] & 0x08) { svga->htotal <<= 1; svga->hdisp <<= 1; @@ -760,7 +826,24 @@ tgui_recalctimings(svga_t *svga) switch (svga->bpp) { case 8: svga->render = svga_render_8bpp_highres; + if (svga->vdisp == 1022) { + if (svga->interlace) + svga->dispend++; + else + svga->dispend += 2; + } if (tgui->type >= TGUI_9660) { + switch (svga->vdisp) { + case 1024: + case 1200: + svga->htotal <<= 1; + svga->hdisp <<= 1; + svga->hdisp_time <<= 1; + break; + default: + break; + } +#if OLD_CODE if (svga->dispend == ((1024 >> 1) - 2)) svga->dispend += 2; if (svga->dispend == (1024 >> 1)) @@ -773,6 +856,7 @@ tgui_recalctimings(svga_t *svga) else if (!svga->interlace && (svga->dispend == 768)) svga->hdisp <<= 1; } +#endif if (ger22upper & 0x80) { svga->htotal <<= 1; @@ -782,7 +866,7 @@ tgui_recalctimings(svga_t *svga) switch (svga->hdisp) { case 640: if (!ger22lower) - svga->rowoffset = 80; + svga->rowoffset = 0x50; break; default: @@ -806,11 +890,10 @@ tgui_recalctimings(svga_t *svga) svga->hdisp = (svga->hdisp << 1) / 3; break; case 32: + if (svga->rowoffset == 0x100) + svga->rowoffset <<= 1; + svga->render = svga_render_32bpp_highres; - if (tgui->type >= TGUI_9660) { - if (!ger22upper) - svga->rowoffset <<= 1; - } break; default: @@ -825,14 +908,14 @@ tgui_recalcmapping(tgui_t *tgui) svga_t *svga = &tgui->svga; if (tgui->type == TGUI_9400CXI) { - if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { + if (svga->gdcreg[0x10] & EXT_CTRL_LATCH_COPY) { mem_mapping_set_handler(&tgui->linear_mapping, tgui_ext_linear_read, NULL, NULL, tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); mem_mapping_set_handler(&svga->mapping, tgui_ext_read, NULL, NULL, tgui_ext_write, tgui_ext_writew, tgui_ext_writel); - } else if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_EXPANSION) { + } else if (svga->gdcreg[0x10] & EXT_CTRL_MONO_EXPANSION) { mem_mapping_set_handler(&tgui->linear_mapping, svga_read_linear, svga_readw_linear, svga_readl_linear, tgui_ext_linear_write, tgui_ext_linear_writew, tgui_ext_linear_writel); @@ -928,7 +1011,7 @@ tgui_recalcmapping(tgui_t *tgui) } if (tgui->type >= TGUI_9440) { - if ((tgui->mmio_base != 0x00000000) && (svga->crtc[0x39] & 1)) + if ((tgui->mmio_base != 0x00000000) && (svga->crtc[0x39] & 0x01)) mem_mapping_set_addr(&tgui->mmio_mapping, tgui->mmio_base, 0x10000); else mem_mapping_disable(&tgui->mmio_mapping); @@ -939,7 +1022,7 @@ static void tgui_hwcursor_draw(svga_t *svga, int displine) { uint32_t dat[2]; - int offset = svga->hwcursor_latch.x + svga->hwcursor_latch.xoff; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; int pitch = (svga->hwcursor_latch.cur_xsize == 64) ? 16 : 8; if (svga->interlace && svga->hwcursor_oddeven) @@ -1121,26 +1204,24 @@ tgui_ext_linear_read(uint32_t addr, void *priv) svga_t *svga = (svga_t *) priv; tgui_t *tgui = (tgui_t *) svga->priv; - cycles -= video_timing_read_b; + cycles -= svga->monitor->mon_video_timing_read_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xff; addr &= svga->vram_mask; - addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; - addr = dword_remap(svga, addr); + addr &= ~0x0f; + addr = dword_remap(svga, addr); - if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { - for (int c = 0; c < 16; c++) { - tgui->copy_latch[c] = svga->vram[addr]; - addr += (c & 3) ? 1 : 13; - addr &= svga->vram_mask; - } - return svga->vram[addr]; + for (int i = 0; i < 16; i++) { + tgui->copy_latch[i] = svga->vram[addr]; + addr += ((i & 3) == 3) ? 0x0d : 0x01; } - return svga_read_linear(addr, svga); + addr &= svga->vram_mask; + + return svga->vram[addr]; } static uint8_t @@ -1158,65 +1239,77 @@ tgui_ext_linear_write(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; const tgui_t *tgui = (tgui_t *) svga->priv; - int c; - int bpp = (tgui->ext_gdc_regs[0] & EXT_CTRL_16BIT); - uint8_t fg[2] = { tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5] }; - uint8_t bg[2] = { tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2] }; - uint8_t mask = tgui->ext_gdc_regs[7]; + int bpp = (svga->gdcreg[0x10] & EXT_CTRL_16BIT); + uint8_t fg[2] = { svga->gdcreg[0x14], svga->gdcreg[0x15] }; + uint8_t bg[2] = { svga->gdcreg[0x11], svga->gdcreg[0x12] }; - cycles -= video_timing_write_b; + cycles -= svga->monitor->mon_video_timing_write_b; addr &= svga->decode_mask; if (addr >= svga->vram_max) return; + addr &= svga->vram_mask; - addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; + addr &= (svga->gdcreg[0x10] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; + addr = dword_remap(svga, addr); - addr = dword_remap(svga, addr); svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; - if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { - for (c = 0; c < 16; c++) { - svga->vram[addr] = tgui->copy_latch[c]; - addr += ((c & 3) == 3) ? 13 : 1; + if (svga->gdcreg[0x10] & EXT_CTRL_LATCH_COPY) { + for (int i = 0; i < 8; i++) { + if (val & (0x80 >> i)) + svga->vram[addr] = tgui->copy_latch[i]; + + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } - } else if (tgui->ext_gdc_regs[0] & (EXT_CTRL_MONO_EXPANSION | EXT_CTRL_MONO_TRANSPARENT)) { - if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_TRANSPARENT) { + } else { + if (svga->gdcreg[0x10] & EXT_CTRL_MONO_TRANSPARENT) { if (bpp) { - for (c = 7; c >= 0; c--) { - if ((val & mask) & (1 << c)) - svga->vram[addr] = fg[(c & 1) ^ 1]; - addr += (c & 3) ? 1 : 13; + for (int i = 0; i < 8; i++) { + if (val & (0x80 >> i)) + svga->vram[addr] = fg[i & 1]; + + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } else { - for (c = 7; c >= 0; c--) { - if ((val & mask) & (1 << c)) - svga->vram[addr] = tgui->ext_gdc_regs[4]; - addr += (c == 4) ? 13 : 1; + for (int i = 0; i < 8; i++) { + if (val & (0x80 >> i)) + svga->vram[addr] = fg[0]; + + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } } else { if (bpp) { - for (c = 7; c >= 0; c--) { - if (mask & (1 << c)) - svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; - addr += (c & 3) ? 1 : 13; + for (int i = 0; i < 8; i++) { + if (val & (0x80 >> i)) { + if (svga->gdcreg[0x17] & (0x80 >> i)) + svga->vram[addr] = fg[i & 1]; + } else { + if (svga->gdcreg[0x17] & (0x80 >> i)) + svga->vram[addr] = bg[i & 1]; + } + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } else { - for (c = 7; c >= 0; c--) { - if (mask & (1 << c)) - svga->vram[addr] = (val & (1 << c)) ? tgui->ext_gdc_regs[4] : tgui->ext_gdc_regs[1]; - addr += (c == 4) ? 13 : 1; + for (int i = 0; i < 8; i++) { + if (val & (0x80 >> i)) { + if (svga->gdcreg[0x17] & (0x80 >> i)) + svga->vram[addr] = fg[0]; + } else { + if (svga->gdcreg[0x17] & (0x80 >> i)) + svga->vram[addr] = bg[0]; + } + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } } - } else - svga_write_linear(addr, val, svga); + } } static void @@ -1224,94 +1317,85 @@ tgui_ext_linear_writew(uint32_t addr, uint16_t val, void *priv) { svga_t *svga = (svga_t *) priv; const tgui_t *tgui = (tgui_t *) svga->priv; - int c; - int bpp = (tgui->ext_gdc_regs[0] & EXT_CTRL_16BIT); - uint8_t fg[2] = { tgui->ext_gdc_regs[4], tgui->ext_gdc_regs[5] }; - uint8_t bg[2] = { tgui->ext_gdc_regs[1], tgui->ext_gdc_regs[2] }; - uint16_t mask = (tgui->ext_gdc_regs[7] << 8) | tgui->ext_gdc_regs[8]; + int bpp = (svga->gdcreg[0x10] & EXT_CTRL_16BIT); + uint8_t fg[2] = { svga->gdcreg[0x14], svga->gdcreg[0x15] }; + uint8_t bg[2] = { svga->gdcreg[0x11], svga->gdcreg[0x12] }; + uint16_t mask = svga->gdcreg[0x18] | (svga->gdcreg[0x17] << 8); - cycles -= video_timing_write_w; + cycles -= svga->monitor->mon_video_timing_write_w; addr &= svga->decode_mask; if (addr >= svga->vram_max) return; + addr &= svga->vram_mask; - addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; + addr &= ~0x0f; + addr = dword_remap(svga, addr); - addr = dword_remap(svga, addr); svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; - val = (val >> 8) | (val << 8); - if (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) { - for (c = 0; c < 16; c++) { - svga->vram[addr] = tgui->copy_latch[c]; - addr += (c & 3) ? 1 : 13; + if (svga->gdcreg[0x10] & EXT_CTRL_LATCH_COPY) { + for (int i = 0; i < 16; i++) { + if (val & (0x8000 >> i)) + svga->vram[addr] = tgui->copy_latch[i]; + + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } - } else if (tgui->ext_gdc_regs[0] & (EXT_CTRL_MONO_EXPANSION | EXT_CTRL_MONO_TRANSPARENT)) { - if (tgui->ext_gdc_regs[0] & EXT_CTRL_MONO_TRANSPARENT) { + } else { + if (svga->gdcreg[0x10] & EXT_CTRL_MONO_TRANSPARENT) { if (bpp) { - for (c = 15; c >= 0; c--) { - if ((val & mask) & (1 << c)) - svga->vram[addr] = fg[(c & 1) ^ 1]; - addr += (c & 3) ? 1 : 13; + for (int i = 0; i < 16; i++) { + if (val & (0x8000 >> i)) + svga->vram[addr] = fg[i & 1]; + + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } else { - for (c = 15; c >= 0; c--) { - if ((val & mask) & (1 << c)) - svga->vram[addr] = tgui->ext_gdc_regs[4]; + for (int i = 0; i < 16; i++) { + if (val & (0x8000 >> i)) + svga->vram[addr] = fg[0]; - addr += (c & 3) ? 1 : 13; + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } } else { if (bpp) { - for (c = 15; c >= 0; c--) { - if (mask & (1 << c)) - svga->vram[addr] = (val & (1 << c)) ? fg[(c & 1) ^ 1] : bg[(c & 1) ^ 1]; - addr += (c & 3) ? 1 : 13; + for (int i = 0; i < 16; i++) { + if (val & (0x8000 >> i)) { + if (mask & (0x8000 >> i)) + svga->vram[addr] = fg[i & 1]; + } else { + if (mask & (0x8000 >> i)) + svga->vram[addr] = bg[i & 1]; + } + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } else { - for (c = 15; c >= 0; c--) { - if (mask & (1 << c)) - svga->vram[addr] = (val & (1 << c)) ? tgui->ext_gdc_regs[4] : tgui->ext_gdc_regs[1]; - - addr += (c & 3) ? 1 : 13; + for (int i = 0; i < 16; i++) { + if (val & (0x8000 >> i)) { + if (mask & (0x8000 >> i)) + svga->vram[addr] = fg[0]; + } else { + if (mask & (0x8000 >> i)) + svga->vram[addr] = bg[0]; + } + addr += ((i & 3) == 3) ? 0x0d : 0x01; addr &= svga->vram_mask; } } } - } else - svga_writew_linear(addr, val, svga); + } } static void tgui_ext_linear_writel(uint32_t addr, uint32_t val, void *priv) { - svga_t *svga = (svga_t *) priv; - const tgui_t *tgui = (tgui_t *) svga->priv; - - cycles -= video_timing_write_l; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - addr &= (tgui->ext_gdc_regs[0] & EXT_CTRL_LATCH_COPY) ? ~0x0f : ~0x07; - - addr = dword_remap(svga, addr); - svga->changedvram[addr >> 12] = svga->monitor->mon_changeframecount; - - if (tgui->ext_gdc_regs[0] & (EXT_CTRL_MONO_EXPANSION | EXT_CTRL_MONO_TRANSPARENT | EXT_CTRL_LATCH_COPY)) { - tgui_ext_linear_writew(addr, val & 0xffff, priv); - tgui_ext_linear_writew(addr + 2, val >> 16, priv); - } else { - svga_writel_linear(addr, val, svga); - } + tgui_ext_linear_writew(addr, val, priv); } static void @@ -1484,6 +1568,8 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) case 32: tgui->accel.pitch <<= 1; break; + default: + break; } #if 0 pclog("TGUI accel command = %x, ger22 = %04x, hdisp = %d, dispend = %d, vtotal = %d, rowoffset = %d, svgabpp = %d, interlace = %d, accelbpp = %d, pitch = %d.\n", tgui->accel.command, tgui->accel.ger22, svga->hdisp, svga->dispend, svga->vtotal, svga->rowoffset, svga->bpp, svga->interlace, tgui->accel.bpp, tgui->accel.pitch); @@ -3213,7 +3299,6 @@ tgui_init(const device_t *info) if (tgui->type >= TGUI_9440) { svga->packed_chain4 = 1; - tgui->i2c = i2c_gpio_init("ddc_tgui"); tgui->ddc = ddc_init(i2c_gpio_get_bus(tgui->i2c)); } diff --git a/src/video/vid_tvp3026_ramdac.c b/src/video/vid_tvp3026_ramdac.c index b50d0406b2..6c001b4616 100644 --- a/src/video/vid_tvp3026_ramdac.c +++ b/src/video/vid_tvp3026_ramdac.c @@ -516,7 +516,7 @@ tvp3026_recalctimings(void *priv, svga_t *svga) svga->interlace = !!(ramdac->ccr & 0x40); /* TODO: Figure out gamma correction for 15/16 bpp color. */ - svga->lut_map = !!(svga->bpp >= 15 && (ramdac->true_color & 0xf0) != 0x00); + svga->lut_map = !!((svga->bpp >= 15 && (svga->bpp != 24)) && (ramdac->true_color & 0xf0) != 0x00); if (!(ramdac->clock_sel & 0x70)) { if (ramdac->mcr != 0x98) { diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index 8b2e761a3a..881a3c6fde 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -31,6 +31,7 @@ #include <86box/vid_svga.h> #include <86box/vid_vga.h> +static video_timings_t timing_vga = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 }; static video_timings_t timing_ps1_svga_isa = { .type = VIDEO_ISA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; static video_timings_t timing_ps1_svga_mca = { .type = VIDEO_MCA, .write_b = 6, .write_w = 8, .write_l = 16, .read_b = 6, .read_w = 8, .read_l = 16 }; @@ -207,7 +208,7 @@ const device_t ps1vga_device = { .init = ps1vga_init, .close = vga_close, .reset = NULL, - { .available = vga_available }, + { .available = NULL }, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL @@ -221,7 +222,7 @@ const device_t ps1vga_mca_device = { .init = ps1vga_init, .close = vga_close, .reset = NULL, - { .available = vga_available }, + { .available = NULL }, .speed_changed = vga_speed_changed, .force_redraw = vga_force_redraw, .config = NULL diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 93bdd1a4cb..efa2d20c85 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -222,12 +222,12 @@ voodoo_readl(uint32_t addr, void *priv) { int fifo_entries = FIFO_ENTRIES; int swap_count = voodoo->swap_count; - int written = voodoo->cmd_written + voodoo->cmd_written_fifo; + int written = voodoo->cmd_written + voodoo->cmd_written_fifo + voodoo->cmd_written_fifo_2; int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr); if (SLI_ENABLED && voodoo->type != VOODOO_2) { voodoo_t *voodoo_other = (voodoo == voodoo->set->voodoos[0]) ? voodoo->set->voodoos[1] : voodoo->set->voodoos[0]; - int other_written = voodoo_other->cmd_written + voodoo_other->cmd_written_fifo; + int other_written = voodoo_other->cmd_written + voodoo_other->cmd_written_fifo + voodoo->cmd_written_fifo_2; if (voodoo_other->swap_count > swap_count) swap_count = voodoo_other->swap_count; diff --git a/src/video/vid_voodoo_banshee.c b/src/video/vid_voodoo_banshee.c index 5b6dbb4341..c1fb65b001 100644 --- a/src/video/vid_voodoo_banshee.c +++ b/src/video/vid_voodoo_banshee.c @@ -204,6 +204,17 @@ enum { cmdFifoDepth0 = 0x44, cmdHoleCnt0 = 0x48, + cmdBaseAddr1 = 0x50, + cmdBaseSize1 = 0x50 + 0x4, + cmdBump1 = 0x50 + 0x8, + cmdRdPtrL1 = 0x50 + 0xc, + cmdRdPtrH1 = 0x50 + 0x10, + cmdAMin1 = 0x50 + 0x14, + cmdAMax1 = 0x50 + 0x1c, + cmdStatus1 = 0x50 + 0x20, + cmdFifoDepth1 = 0x50 + 0x24, + cmdHoleCnt1 = 0x50 + 0x28, + Agp_agpReqSize = 0x00, Agp_agpHostAddressLow = 0x04, Agp_agpHostAddressHigh = 0x08, @@ -513,7 +524,7 @@ banshee_render_16bpp_tiled(svga_t *svga) if (addr >= svga->vram_max) return; - for (int x = 0; x <= svga->hdisp; x += 64) { + for (int x = 0; x < svga->hdisp; x += 64) { if (svga->hwcursor_on || svga->overlay_on) svga->changedvram[addr >> 12] = 2; if (svga->changedvram[addr >> 12] || svga->fullchange) { @@ -1341,6 +1352,29 @@ banshee_cmd_read(banshee_t *banshee, uint32_t addr) ret = voodoo->cmdfifo_size; break; + case cmdBaseAddr1: + ret = voodoo->cmdfifo_base_2 >> 12; + // banshee_log("Read cmdfifo_base %08x\n", ret); + break; + + case cmdRdPtrL1: + ret = voodoo->cmdfifo_rp_2; + // banshee_log("Read cmdfifo_rp %08x\n", ret); + break; + + case cmdFifoDepth1: + ret = voodoo->cmdfifo_depth_wr_2 - voodoo->cmdfifo_depth_rd_2; + // banshee_log("Read cmdfifo_depth %08x\n", ret); + break; + + case cmdStatus1: + ret = voodoo->cmd_status_2; + break; + + case cmdBaseSize1: + ret = voodoo->cmdfifo_size_2; + break; + case 0x108: break; @@ -1625,6 +1659,45 @@ banshee_cmd_write(banshee_t *banshee, uint32_t addr, uint32_t val) voodoo->cmdfifo_depth_wr = val & 0xffff; break; + case cmdBaseAddr1: + voodoo->cmdfifo_base_2 = (val & 0xfff) << 12; + voodoo->cmdfifo_end_2 = voodoo->cmdfifo_base_2 + (((voodoo->cmdfifo_size_2 & 0xff) + 1) << 12); +#if 0 + banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x %08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end, val); +#endif + break; + + case cmdBaseSize1: + voodoo->cmdfifo_size_2 = val; + voodoo->cmdfifo_end_2 = voodoo->cmdfifo_base_2 + (((voodoo->cmdfifo_size_2 & 0xff) + 1) << 12); + voodoo->cmdfifo_enabled_2 = val & 0x100; + if (!voodoo->cmdfifo_enabled_2) + voodoo->cmdfifo_in_sub_2 = 0; /*Not sure exactly when this should be reset*/ +#if 0 + banshee_log("cmdfifo_base=%08x cmdfifo_end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); +#endif + break; + +#if 0 + voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12; + banshee_log("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end); + break; +#endif + + case cmdRdPtrL1: + voodoo->cmdfifo_rp_2 = val; + break; + case cmdAMin1: + voodoo->cmdfifo_amin_2 = val; + break; + case cmdAMax1: + voodoo->cmdfifo_amax_2 = val; + break; + case cmdFifoDepth1: + voodoo->cmdfifo_depth_rd_2 = 0; + voodoo->cmdfifo_depth_wr_2 = val & 0xffff; + break; + default: banshee_log("Unknown banshee_cmd_write: addr=%08x val=%08x reg=0x%03x\n", addr, val, addr & 0x1fc); break; @@ -2064,6 +2137,60 @@ banshee_write_linear_l(uint32_t addr, uint32_t val, void *priv) voodoo->cmdfifo_holecount = ((voodoo->cmdfifo_amax - voodoo->cmdfifo_amin) >> 2) - 1; #if 0 banshee_log("CMDFIFO out of order: amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); +#endif + } + } + + if (voodoo->cmdfifo_enabled_2 && addr >= voodoo->cmdfifo_base_2 && addr < voodoo->cmdfifo_end_2) { +#if 0 + banshee_log("CMDFIFO write %08x %08x old amin=%08x amax=%08x hlcnt=%i depth_wr=%i rp=%08x\n", addr, val, voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount, voodoo->cmdfifo_depth_wr, voodoo->cmdfifo_rp); +#endif + if (addr == voodoo->cmdfifo_base_2 && !voodoo->cmdfifo_holecount_2) { +#if 0 + if (voodoo->cmdfifo_holecount) + fatal("CMDFIFO reset pointers while outstanding holes\n"); +#endif + /*Reset pointers*/ + voodoo->cmdfifo_amin_2 = voodoo->cmdfifo_base_2; + voodoo->cmdfifo_amax_2 = voodoo->cmdfifo_base_2; + voodoo->cmdfifo_depth_wr_2++; + voodoo_wake_fifo_thread(voodoo); + } else if (voodoo->cmdfifo_holecount_2) { +#if 0 + if ((addr <= voodoo->cmdfifo_amin && voodoo->cmdfifo_amin != -4) || addr >= voodoo->cmdfifo_amax) + fatal("CMDFIFO holecount write outside of amin/amax - amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); + banshee_log("holecount %i\n", voodoo->cmdfifo_holecount); +#endif + voodoo->cmdfifo_holecount_2--; + if (!voodoo->cmdfifo_holecount_2) { + /*Filled in holes, resume normal operation*/ + voodoo->cmdfifo_depth_wr_2 += ((voodoo->cmdfifo_amax_2 - voodoo->cmdfifo_amin_2) >> 2); + voodoo->cmdfifo_amin_2 = voodoo->cmdfifo_amax_2; + voodoo_wake_fifo_thread(voodoo); +#if 0 + banshee_log("hole filled! amin=%08x amax=%08x added %i words\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, words_to_add); +#endif + } + } else if (addr == voodoo->cmdfifo_amax_2 + 4) { + /*In-order write*/ + voodoo->cmdfifo_amin_2 = addr; + voodoo->cmdfifo_amax_2 = addr; + voodoo->cmdfifo_depth_wr_2++; + voodoo_wake_fifo_thread(voodoo); + } else { + /*Out-of-order write*/ + if (addr < voodoo->cmdfifo_amin_2) { + /*Reset back to start. Note that write is still out of order!*/ + voodoo->cmdfifo_amin_2 = voodoo->cmdfifo_base_2 - 4; + } +#if 0 + else if (addr < voodoo->cmdfifo_amax) + fatal("Out-of-order write really out of order\n"); +#endif + voodoo->cmdfifo_amax_2 = addr; + voodoo->cmdfifo_holecount_2 = ((voodoo->cmdfifo_amax_2 - voodoo->cmdfifo_amin_2) >> 2) - 1; +#if 0 + banshee_log("CMDFIFO out of order: amin=%08x amax=%08x holecount=%i\n", voodoo->cmdfifo_amin, voodoo->cmdfifo_amax, voodoo->cmdfifo_holecount); #endif } } @@ -3313,6 +3440,7 @@ banshee_init_common(const device_t *info, char *fn, int has_sgram, int type, int banshee->voodoo->tex_mem_w[1] = (uint16_t *) banshee->svga.vram; banshee->voodoo->texture_mask = banshee->svga.vram_mask; banshee->voodoo->cmd_status = (1 << 28); + banshee->voodoo->cmd_status_2 = (1 << 28); voodoo_generate_filter_v1(banshee->voodoo); banshee->vidSerialParallelPort = VIDSERIAL_DDC_DCK_W | VIDSERIAL_DDC_DDA_W; diff --git a/src/video/vid_voodoo_banshee_blitter.c b/src/video/vid_voodoo_banshee_blitter.c index b8809d3fd7..4dc39f3325 100644 --- a/src/video/vid_voodoo_banshee_blitter.c +++ b/src/video/vid_voodoo_banshee_blitter.c @@ -346,6 +346,7 @@ update_src_stride(voodoo_t *voodoo) break; case SRC_FORMAT_COL_32_BPP: case SRC_FORMAT_COL_YUYV: + case SRC_FORMAT_COL_UYVY: bpp = 32; break; @@ -731,6 +732,13 @@ do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int sr src_data_yuv = *(uint32_t *) &src_p[src_x_real]; break; } + case SRC_FORMAT_COL_UYVY: + { + src_data_yuv = *(uint32_t *) &src_p[src_x_real]; + src_data_yuv = ((src_data_yuv & 0xFF00) >> 8) | ((src_data_yuv & 0xFF) << 8) | + ((src_data_yuv & 0xFF000000) >> 8) | ((src_data_yuv & 0xFF0000) << 8); + break; + } default: fatal("banshee_do_screen_to_screen_blt: unknown srcFormat %08x\n", voodoo->banshee_blt.srcFormat); @@ -744,7 +752,8 @@ do_screen_to_screen_line(voodoo_t *voodoo, uint8_t *src_p, int use_x_dir, int sr src_data = (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); } - if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_YUYV) { + if ((voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_YUYV + || (voodoo->banshee_blt.srcFormat & SRC_FORMAT_COL_MASK) == SRC_FORMAT_COL_UYVY) { if (((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_24_BPP) || ((voodoo->banshee_blt.dstFormat & DST_FORMAT_COL_MASK) == DST_FORMAT_COL_32_BPP)) { uint32_t rgbcol[2] = { 0, 0 }; @@ -1488,6 +1497,7 @@ voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val) break; case SRC_FORMAT_COL_32_BPP: case SRC_FORMAT_COL_YUYV: + case SRC_FORMAT_COL_UYVY: voodoo->banshee_blt.src_bpp = 32; break; case SRC_FORMAT_COL_16_BPP: diff --git a/src/video/vid_voodoo_fb.c b/src/video/vid_voodoo_fb.c index 94394e1157..5ae26b4c57 100644 --- a/src/video/vid_voodoo_fb.c +++ b/src/video/vid_voodoo_fb.c @@ -364,6 +364,35 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) addr >>= 1; break; + case LFB_FORMAT_XRGB8888: + colour_data[0].b = val & 0xff; + colour_data[0].g = (val >> 8) & 0xff; + colour_data[0].r = (val >> 16) & 0xff; + alpha_data[0] = 0xff; + write_mask = LFB_WRITE_COLOUR; + addr >>= 1; + break; + + case LFB_FORMAT_DEPTH_RGB565: + colour_data[0] = rgb565[val & 0xffff]; + depth_data[0] = val >> 16; + write_mask = LFB_WRITE_BOTH; + count = 1; + break; + case LFB_FORMAT_DEPTH_RGB555: + colour_data[0] = argb1555[val & 0xffff]; + depth_data[0] = val >> 16; + write_mask = LFB_WRITE_BOTH; + count = 1; + break; + case LFB_FORMAT_DEPTH_ARGB1555: + colour_data[0] = argb1555[val & 0xffff]; + alpha_data[0] = colour_data[0].a; + depth_data[0] = val >> 16; + write_mask = LFB_WRITE_BOTH; + count = 1; + break; + case LFB_FORMAT_DEPTH: depth_data[0] = val; depth_data[1] = val >> 16; @@ -460,9 +489,15 @@ voodoo_fb_writel(uint32_t addr, uint32_t val, void *priv) } else { for (int c = 0; c < count; c++) { if (write_mask & LFB_WRITE_COLOUR) - *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = + do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); if (write_mask & LFB_WRITE_DEPTH) *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; + if (write_mask & LFB_WRITE_BOTH) { + *(uint16_t *) (&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = + do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); + *(uint16_t *) (&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; + } write_addr += 2; write_addr_aux += 2; diff --git a/src/video/vid_voodoo_fifo.c b/src/video/vid_voodoo_fifo.c index f8495edec9..54a0140f69 100644 --- a/src/video/vid_voodoo_fifo.c +++ b/src/video/vid_voodoo_fifo.c @@ -188,6 +188,40 @@ cmdfifo_get_f(voodoo_t *voodoo) return tempif.f; } +static uint32_t +cmdfifo_get_2(voodoo_t *voodoo) +{ + uint32_t val; + + if (!voodoo->cmdfifo_in_sub_2) { + while (voodoo->fifo_thread_run && (voodoo->cmdfifo_depth_rd_2 == voodoo->cmdfifo_depth_wr_2)) { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + } + } + + val = *(uint32_t *) &voodoo->fb_mem[voodoo->cmdfifo_rp_2 & voodoo->fb_mask]; + + if (!voodoo->cmdfifo_in_sub_2) + voodoo->cmdfifo_depth_rd_2++; + voodoo->cmdfifo_rp_2 += 4; + + // voodoo_fifo_log(" CMDFIFO get %08x\n", val); + return val; +} + +static inline float +cmdfifo_get_f_2(voodoo_t *voodoo) +{ + union { + uint32_t i; + float f; + } tempif; + + tempif.i = cmdfifo_get_2(voodoo); + return tempif.f; +} + enum { CMDFIFO3_PC_MASK_RGB = (1 << 10), CMDFIFO3_PC_MASK_ALPHA = (1 << 11), @@ -283,6 +317,7 @@ voodoo_fifo_thread(void *param) } voodoo->cmd_status |= (1 << 24); + voodoo->cmd_status_2 |= (1 << 24); while (voodoo->cmdfifo_enabled && (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr || voodoo->cmdfifo_in_sub)) { uint64_t start_time = plat_timer_read(); @@ -545,6 +580,269 @@ voodoo_fifo_thread(void *param) end_time = plat_timer_read(); voodoo->time += end_time - start_time; } + + while (voodoo->cmdfifo_enabled_2 && (voodoo->cmdfifo_depth_rd_2 != voodoo->cmdfifo_depth_wr_2 || voodoo->cmdfifo_in_sub_2)) { + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + uint32_t header = cmdfifo_get_2(voodoo); + uint32_t addr; + uint32_t mask; + int smode; + int num; + int num_verticies; + int v_num; + +#if 0 + voodoo_fifo_log(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); +#endif + + voodoo->cmd_status_2 &= ~7; + voodoo->cmd_status_2 |= (header & 7); + voodoo->cmd_status_2 |= (1 << 11); + switch (header & 7) { + case 0: +#if 0 + voodoo_fifo_log("CMDFIFO0\n"); +#endif + voodoo->cmd_status_2 = (voodoo->cmd_status_2 & 0xffff8fff) | (((header >> 3) & 7) << 12); + switch ((header >> 3) & 7) { + case 0: /*NOP*/ + break; + + case 1: /*JSR*/ +#if 0 + voodoo_fifo_log("JSR %08x\n", (header >> 4) & 0xfffffc); +#endif + voodoo->cmdfifo_ret_addr_2 = voodoo->cmdfifo_rp_2; + voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc; + voodoo->cmdfifo_in_sub_2 = 1; + break; + + case 2: /*RET*/ + voodoo->cmdfifo_rp_2 = voodoo->cmdfifo_ret_addr_2; + voodoo->cmdfifo_in_sub_2 = 0; + break; + + case 3: /*JMP local frame buffer*/ + voodoo->cmdfifo_rp_2 = (header >> 4) & 0xfffffc; +#if 0 + voodoo_fifo_log("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); +#endif + break; + + default: + fatal("Bad CMDFIFO0 %08x\n", header); + } + voodoo->cmd_status_2 = (voodoo->cmd_status_2 & ~(1 << 27)) | (voodoo->cmdfifo_in_sub_2 << 27); + break; + + case 1: + num = header >> 16; + addr = (header & 0x7ff8) >> 1; +#if 0 + voodoo_fifo_log("CMDFIFO1 addr=%08x\n",addr); +#endif + while (num--) { + uint32_t val = cmdfifo_get_2(voodoo); + if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) { +#if 0 + if (voodoo->type != VOODOO_BANSHEE) + fatal("CMDFIFO1: Not Banshee\n"); +#endif + +#if 0 + voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val); +#endif + voodoo_2d_reg_writel(voodoo, addr, val); + } else { + if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) + voodoo->cmd_written_fifo_2++; + + if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD) + voodoo->cmd_written_fifo_2++; + voodoo_reg_writel(addr, val, voodoo); + } + + if (header & (1 << 15)) + addr += 4; + } + break; + + case 2: + if (voodoo->type < VOODOO_2) + fatal("CMDFIFO2: Not Voodoo 2\n"); + mask = (header >> 3); + addr = 8; + while (mask) { + if (mask & 1) { + uint32_t val = cmdfifo_get_2(voodoo); + + voodoo_2d_reg_writel(voodoo, addr, val); + } + + addr += 4; + mask >>= 1; + } + break; + + case 3: + num = (header >> 29) & 7; + mask = header; //(header >> 10) & 0xff; + smode = (header >> 22) & 0xf; + voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo); + num_verticies = (header >> 6) & 0xf; + v_num = 0; + if (((header >> 3) & 7) == 2) + v_num = 1; +#if 0 + voodoo_fifo_log("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); + voodoo_fifo_log("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); +#endif + + while (num_verticies--) { + voodoo->verts[3].sVx = cmdfifo_get_f_2(voodoo); + voodoo->verts[3].sVy = cmdfifo_get_f_2(voodoo); + if (mask & CMDFIFO3_PC_MASK_RGB) { + if (header & CMDFIFO3_PC) { + uint32_t val = cmdfifo_get_2(voodoo); + voodoo->verts[3].sBlue = (float) (val & 0xff); + voodoo->verts[3].sGreen = (float) ((val >> 8) & 0xff); + voodoo->verts[3].sRed = (float) ((val >> 16) & 0xff); + voodoo->verts[3].sAlpha = (float) ((val >> 24) & 0xff); + } else { + voodoo->verts[3].sRed = cmdfifo_get_f_2(voodoo); + voodoo->verts[3].sGreen = cmdfifo_get_f_2(voodoo); + voodoo->verts[3].sBlue = cmdfifo_get_f_2(voodoo); + } + } + if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC)) + voodoo->verts[3].sAlpha = cmdfifo_get_f_2(voodoo); + if (mask & CMDFIFO3_PC_MASK_Z) + voodoo->verts[3].sVz = cmdfifo_get_f_2(voodoo); + if (mask & CMDFIFO3_PC_MASK_Wb) + voodoo->verts[3].sWb = cmdfifo_get_f_2(voodoo); + if (mask & CMDFIFO3_PC_MASK_W0) + voodoo->verts[3].sW0 = cmdfifo_get_f_2(voodoo); + if (mask & CMDFIFO3_PC_MASK_S0_T0) { + voodoo->verts[3].sS0 = cmdfifo_get_f_2(voodoo); + voodoo->verts[3].sT0 = cmdfifo_get_f_2(voodoo); + } + if (mask & CMDFIFO3_PC_MASK_W1) + voodoo->verts[3].sW1 = cmdfifo_get_f_2(voodoo); + if (mask & CMDFIFO3_PC_MASK_S1_T1) { + voodoo->verts[3].sS1 = cmdfifo_get_f_2(voodoo); + voodoo->verts[3].sT1 = cmdfifo_get_f_2(voodoo); + } + if (v_num) + voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo); + else + voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo); + v_num++; + if (v_num == 3 && ((header >> 3) & 7) == 0) + v_num = 0; + } + while (num--) + cmdfifo_get_2(voodoo); + break; + + case 4: + num = (header >> 29) & 7; + mask = (header >> 15) & 0x3fff; + addr = (header & 0x7ff8) >> 1; +#if 0 + voodoo_fifo_log("CMDFIFO4 addr=%08x\n",addr); +#endif + while (mask) { + if (mask & 1) { + uint32_t val = cmdfifo_get_2(voodoo); + + if ((addr & (1 << 13)) && voodoo->type >= VOODOO_BANSHEE) { + if (voodoo->type < VOODOO_BANSHEE) + fatal("CMDFIFO1: Not Banshee\n"); +#if 0 + voodoo_fifo_log("CMDFIFO1: write %08x %08x\n", addr, val); +#endif + + voodoo_2d_reg_writel(voodoo, addr, val); + } else { + if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) + voodoo->cmd_written_fifo_2++; + + if (voodoo->type >= VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD) + voodoo->cmd_written_fifo_2++; + voodoo_reg_writel(addr, val, voodoo); + } + } + + addr += 4; + mask >>= 1; + } + while (num--) + cmdfifo_get_2(voodoo); + break; + + case 5: +#if 0 + if (header & 0x3fc00000) + fatal("CMDFIFO packet 5 has byte disables set %08x\n", header); +#endif + num = (header >> 3) & 0x7ffff; + addr = cmdfifo_get_2(voodoo) & 0xffffff; + if (!num) + num = 1; +#if 0 + voodoo_fifo_log("CMDFIFO5 addr=%08x num=%i\n", addr, num); +#endif + switch (header >> 30) { + case 0: /*Linear framebuffer (Banshee)*/ + case 1: /*Planar YUV*/ + if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0); + } + if (voodoo->texture_present[1][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) { +#if 0 + voodoo_fifo_log("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); +#endif + flush_texture_cache(voodoo, addr & voodoo->texture_mask, 1); + } + while (num--) { + uint32_t val = cmdfifo_get_2(voodoo); + if (addr <= voodoo->fb_mask) + *(uint32_t *) &voodoo->fb_mem[addr] = val; + addr += 4; + } + break; + case 2: /*Framebuffer*/ + while (num--) { + uint32_t val = cmdfifo_get_2(voodoo); + voodoo_fb_writel(addr, val, voodoo); + addr += 4; + } + break; + case 3: /*Texture*/ + while (num--) { + uint32_t val = cmdfifo_get_2(voodoo); + voodoo_tex_writel(addr, val, voodoo); + addr += 4; + } + break; + + default: + fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp); + } + break; + + default: + fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); + } + + end_time = plat_timer_read(); + voodoo->time += end_time - start_time; + } + voodoo->voodoo_busy = 0; } } diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 9dcdd84b64..e8d6ef715c 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -157,23 +157,41 @@ xga_updatemapping(svga_t *svga) break; case 1: xga_log("XGA: VGA mode address decode enabled.\n"); + if (xga->base_addr_1mb) { + mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); + mem_mapping_enable(&xga->linear_mapping); + } else if (xga->linear_base) { + mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); + mem_mapping_enable(&xga->linear_mapping); + } else + mem_mapping_disable(&xga->linear_mapping); break; case 2: xga_log("XGA: 132-Column mode address decode disabled.\n"); break; case 3: xga_log("XGA: 132-Column mode address decode enabled.\n"); + if (xga->base_addr_1mb) { + mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); + mem_mapping_enable(&xga->linear_mapping); + } else if (xga->linear_base) { + mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); + mem_mapping_enable(&xga->linear_mapping); + } else + mem_mapping_disable(&xga->linear_mapping); break; default: xga_log("XGA: Extended Graphics mode.\n"); switch (xga->aperture_cntl) { case 0: - xga_log("XGA: No 64KB aperture.\n"); - if (xga->base_addr_1mb) + xga_log("XGA: No 64KB aperture: 1MB=%x, 4MB=%x.\n", xga->base_addr_1mb, xga->linear_base); + if (xga->base_addr_1mb) { mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); - else if (xga->linear_base) + mem_mapping_enable(&xga->linear_mapping); + } else if (xga->linear_base) { mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); - else + mem_mapping_enable(&xga->linear_mapping); + } else mem_mapping_disable(&xga->linear_mapping); mem_mapping_disable(&xga->video_mapping); @@ -201,8 +219,8 @@ void xga_recalctimings(svga_t *svga) { xga_t *xga = (xga_t *) svga->xga; - if (xga->on) { + xga->h_total = xga->htotal + 1; xga->v_total = xga->vtotal + 1; xga->dispend = xga->vdispend + 1; xga->v_syncstart = xga->vsyncstart + 1; @@ -211,7 +229,7 @@ xga_recalctimings(svga_t *svga) xga->h_disp = (xga->hdisp + 1) << 3; - xga->rowoffset = xga->hdisp + 1; + xga->rowoffset = xga->pix_map_width; xga->interlace = !!(xga->disp_cntl_1 & 0x08); xga->rowcount = (xga->disp_cntl_2 & 0xc0) >> 6; @@ -226,11 +244,6 @@ xga_recalctimings(svga_t *svga) xga->ma_latch = xga->disp_start_addr; - if ((xga->disp_cntl_2 & 7) == 2) - xga->rowoffset >>= 1; - else if ((xga->disp_cntl_2 & 7) == 4) - xga->rowoffset <<= 1; - xga_log("XGA ClkSel1 = %d, ClkSel2 = %02x.\n", (xga->clk_sel_1 >> 2) & 3, xga->clk_sel_2 & 0x80); switch ((xga->clk_sel_1 >> 2) & 3) { case 0: @@ -371,12 +384,15 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) case 0x40: xga->disp_start_addr = (xga->disp_start_addr & 0x7ff00) | val; + xga_log("DISPSTARTADDR0=%x.\n", xga->disp_start_addr); break; case 0x41: xga->disp_start_addr = (xga->disp_start_addr & 0x700ff) | (val << 8); + xga_log("DISPSTARTADDR8=%x.\n", xga->disp_start_addr); break; case 0x42: xga->disp_start_addr = (xga->disp_start_addr & 0x0ffff) | ((val & 0x07) << 16); + xga_log("DISPSTARTADDR16=%x.\n", xga->disp_start_addr); svga_recalctimings(svga); break; @@ -385,10 +401,11 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) break; case 0x44: xga->pix_map_width = (xga->pix_map_width & 0xff) | ((val & 0x07) << 8); + svga_recalctimings(svga); break; case 0x50: - xga_log("Reg50 write = %02x.\n", val); + xga_log("Reg50 write=%02x.\n", val); xga->disp_cntl_1 = val; svga_recalctimings(svga); break; @@ -417,8 +434,8 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) case 0x60: xga->sprite_pal_addr_idx = (xga->sprite_pal_addr_idx & 0x3f00) | val; - svga->dac_pos = 0; - svga->dac_addr = val & 0xff; + xga->dac_pos = 0; + xga->dac_addr = val & 0xff; break; case 0x61: xga->sprite_pal_addr_idx = (xga->sprite_pal_addr_idx & 0xff) | ((val & 0x3f) << 8); @@ -428,40 +445,32 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) xga->cursor_data_on, xga->sprite_pal_addr_idx, xga->aperture_cntl); break; - case 0x62: - xga->sprite_pal_addr_idx_prefetch = (xga->sprite_pal_addr_idx_prefetch & 0x3f00) | val; - svga->dac_pos = 0; - svga->dac_addr = val & 0xff; - break; - case 0x63: - xga->sprite_pal_addr_idx_prefetch = (xga->sprite_pal_addr_idx_prefetch & 0xff) | ((val & 0x3f) << 8); - xga->sprite_pos_prefetch = xga->sprite_pal_addr_idx_prefetch & 0x1ff; - break; - case 0x64: - svga->dac_mask = val; + xga->dac_mask = val; + xga_log("DAC mask=%02x.\n", val); break; case 0x65: svga->fullchange = svga->monitor->mon_changeframecount; - switch (svga->dac_pos) { + switch (xga->dac_pos) { case 0: - svga->dac_r = val; - svga->dac_pos++; + xga->dac_r = val; + xga->dac_pos++; break; case 1: - svga->dac_g = val; - svga->dac_pos++; + xga->dac_g = val; + xga->dac_pos++; break; case 2: xga->pal_b = val; - index = svga->dac_addr & 0xff; - svga->vgapal[index].r = svga->dac_r; - svga->vgapal[index].g = svga->dac_g; - svga->vgapal[index].b = xga->pal_b; - xga->pallook[index] = makecol32(svga->vgapal[index].r, svga->vgapal[index].g, svga->vgapal[index].b); - svga->dac_pos = 0; - svga->dac_addr = (svga->dac_addr + 1) & 0xff; + index = xga->dac_addr & 0xff; + xga->xgapal[index].r = xga->dac_r; + xga->xgapal[index].g = xga->dac_g; + xga->xgapal[index].b = xga->pal_b; + xga->pallook[index] = makecol32(xga->xgapal[index].r, xga->xgapal[index].g, xga->xgapal[index].b); + xga_log("XGA Pallook=%06x, idx=%d.\n", xga->pallook[index], index); + xga->dac_pos = 0; + xga->dac_addr = (xga->dac_addr + 1) & 0xff; break; default: @@ -470,19 +479,10 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) break; case 0x66: + xga_log("Palette Sequence=%02x.\n", val); xga->pal_seq = val; break; - case 0x67: - svga->dac_r = val; - break; - case 0x68: - xga->pal_b = val; - break; - case 0x69: - svga->dac_g = val; - break; - case 0x6a: xga->sprite_data[xga->sprite_pos] = val; xga->sprite_pos = (xga->sprite_pos + 1) & 0x3ff; @@ -514,10 +514,6 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *priv) xga->aperture_cntl = val & 3; xga_updatemapping(svga); break; - case 4: - if ((xga->disp_cntl_2 & 7) == 4) - xga->aperture_cntl = 0; - break; case 8: xga->ap_idx = val; xga_log("Aperture CNTL = %d, val = %02x, up to bit6 = %02x\n", xga->aperture_cntl, @@ -590,6 +586,9 @@ xga_ext_inb(uint16_t addr, void *priv) case 0x0e: case 0x0f: switch (xga->regs_idx) { + case 0: + ret = (xga->bus & DEVICE_MCA) ? 0x02 : 0x01; + break; case 4: if (xga->bus & DEVICE_MCA) ret = 0x01; /*32-bit MCA*/ @@ -722,32 +721,25 @@ xga_ext_inb(uint16_t addr, void *priv) ret = xga->sprite_pal_addr_idx >> 8; break; - case 0x62: - ret = xga->sprite_pal_addr_idx_prefetch & 0xff; - break; - case 0x63: - ret = xga->sprite_pal_addr_idx_prefetch >> 8; - break; - case 0x64: - ret = svga->dac_mask; + ret = xga->dac_mask; break; case 0x65: - index = svga->dac_addr & 0xff; - switch (svga->dac_pos) { + index = xga->dac_addr & 0xff; + switch (xga->dac_pos) { case 0: - svga->dac_pos++; - ret = svga->vgapal[index].r; + xga->dac_pos++; + ret = xga->xgapal[index].r; break; case 1: - svga->dac_pos++; - ret = svga->vgapal[index].g; + xga->dac_pos++; + ret = xga->xgapal[index].g; break; case 2: - svga->dac_pos = 0; - svga->dac_addr = (svga->dac_addr + 1) & 0xff; - ret = svga->vgapal[index].b; + xga->dac_pos = 0; + xga->dac_addr = (xga->dac_addr + 1) & 0xff; + ret = xga->xgapal[index].b; break; default: @@ -759,21 +751,10 @@ xga_ext_inb(uint16_t addr, void *priv) ret = xga->pal_seq; break; - case 0x67: - ret = svga->dac_r; - break; - case 0x68: - ret = xga->pal_b; - break; - case 0x69: - ret = svga->dac_g; - break; - case 0x6a: - xga_log("Sprite POS Read = %d, addr idx = %04x\n", xga->sprite_pos, - xga->sprite_pal_addr_idx_prefetch); - ret = xga->sprite_data[xga->sprite_pos_prefetch]; - xga->sprite_pos_prefetch = (xga->sprite_pos_prefetch + 1) & 0x3ff; + xga_log("Sprite POS Read=%d.\n", xga->sprite_pos); + ret = xga->sprite_data[xga->sprite_pos]; + xga->sprite_pos = (xga->sprite_pos + 1) & 0x3ff; break; case 0x70: @@ -912,13 +893,8 @@ xga_accel_read_pattern_map_pixel(svga_t *svga, int x, int y, int map, uint32_t b uint8_t px; int skip = 0; - if (xga->base_addr_1mb) { - if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) - skip = 1; - } else { - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) - skip = 1; - } + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) + skip = 1; addr += (y * (width >> 3)); addr += (x >> 3); @@ -956,13 +932,8 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int uint8_t px; int skip = 0; - if (xga->base_addr_1mb) { - if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) - skip = 1; - } else { - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) - skip = 1; - } + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) + skip = 1; switch (xga->accel.px_map_format[map] & 7) { case 0: /*1-bit*/ @@ -1033,13 +1004,8 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui uint8_t mask; int skip = 0; - if (xga->base_addr_1mb) { - if (addr < xga->base_addr_1mb || (addr > (xga->base_addr_1mb + 0xfffff))) - skip = 1; - } else { - if (addr < xga->linear_base || (addr > (xga->linear_base + 0xfffff))) - skip = 1; - } + if ((addr < xga->linear_base) || (addr > (xga->linear_base + 0xfffff))) + skip = 1; switch (xga->accel.px_map_format[map] & 7) { case 0: /*1-bit*/ @@ -1476,7 +1442,8 @@ xga_bitblt(svga_t *svga) if (xga->accel.dst_map_x >= 0x1800) dx |= ~0x17ff; if (xga->accel.dst_map_y >= 0x1800) - dy |= ~0x17ff; + dy -= 0x1800; + xga_log("D(%d,%d), SWH(%d,%d), BLT(%d,%d), dstwidth=%d.\n", dx, dy, xga->accel.x, xga->accel.y, srcwidth, srcheight, dstwidth); xga->accel.pattern = 0; @@ -1755,9 +1722,24 @@ xga_bitblt(svga_t *svga) static void xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) { - addr &= 0x1fff; + uint32_t min_addr; + uint32_t max_addr; + int mmio_addr_enable = 0; + + if (xga_standalone_enabled) { + addr &= 0x1fff; + min_addr = (0x1c00 + (xga->instance << 7)); + max_addr = (0x1c00 + (xga->instance << 7)) + 0x7f; + } else { + addr &= 0x7fff; + min_addr = (0x7c00 + (xga->instance << 7)); + max_addr = (0x7c00 + (xga->instance << 7)) + 0x7f; + } + + if ((addr >= min_addr) && (addr <= max_addr)) + mmio_addr_enable = 1; - if (addr >= 0x1800) { + if (mmio_addr_enable) { switch (addr & 0x7f) { case 0x11: xga->accel.control = val; @@ -2200,7 +2182,6 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len) xga->accel.px_map_format[xga->accel.src_map] & 0x0f, xga->accel.plane_mask); #endif - switch ((xga->accel.command >> 24) & 0x0f) { case 2: /*Short Stroke Vectors Read */ xga_log("Short Stroke Vectors Read.\n"); @@ -2267,7 +2248,7 @@ xga_memio_writeb(uint32_t addr, uint8_t val, void *priv) xga_mem_write(addr, val, xga, svga, 1); - xga_log("Write MEMIOB = %04x, val = %02x\n", addr & 0x7f, val); + xga_log("[%04X:%08X]: Write MEMIOB = %04x, val = %02x\n", CS, cpu_state.pc, addr, val); } static void @@ -2278,7 +2259,7 @@ xga_memio_writew(uint32_t addr, uint16_t val, void *priv) xga_mem_write(addr, val, xga, svga, 2); - xga_log("Write MEMIOW = %04x, val = %04x\n", addr & 0x7f, val); + xga_log("[%04X:%08X]: Write MEMIOW = %04x, val = %04x\n", CS, cpu_state.pc, addr, val); } static void @@ -2289,21 +2270,40 @@ xga_memio_writel(uint32_t addr, uint32_t val, void *priv) xga_mem_write(addr, val, xga, svga, 4); - xga_log("Write MEMIOL = %04x, val = %08x\n", addr & 0x7f, val); + xga_log("[%04X:%08X]: Write MEMIOL = %04x, val = %08x\n", CS, cpu_state.pc, addr, val); } static uint8_t xga_mem_read(uint32_t addr, xga_t *xga, UNUSED(svga_t *svga)) { + uint32_t min_addr; + uint32_t max_addr; uint8_t temp = 0; + int mmio_addr_enable = 0; - addr &= 0x1fff; - if (addr < 0x1800) { - if (xga_standalone_enabled) + if (xga_standalone_enabled) { + addr &= 0x1fff; + min_addr = (0x1c00 + (xga->instance << 7)); + max_addr = (0x1c00 + (xga->instance << 7)) + 0x7f; + if (addr < 0x1c00) temp = xga->bios_rom.rom[addr]; - else - temp = xga->vga_bios_rom.rom[addr]; + else if ((addr >= 0x1c00) && (addr <= 0x1c7f) && xga->instance) + temp = 0xff; + else if ((addr >= min_addr) && (addr <= max_addr)) + mmio_addr_enable = 1; } else { + addr &= 0x7fff; + min_addr = (0x7c00 + (xga->instance << 7)); + max_addr = (0x7c00 + (xga->instance << 7)) + 0x7f; + if (addr < 0x7c00) + temp = xga->bios_rom.rom[addr]; + else if ((addr >= 0x7c00) && (addr <= 0x7c7f) && xga->instance) + temp = 0xff; + else if ((addr >= min_addr) && (addr <= max_addr)) + mmio_addr_enable = 1; + } + + if (mmio_addr_enable) { switch (addr & 0x7f) { case 0x11: temp = xga->accel.control; @@ -2371,8 +2371,8 @@ xga_mem_read(uint32_t addr, xga_t *xga, UNUSED(svga_t *svga)) default: break; } + xga_log("MMIO Addr=%02x, ret=%02x.\n", addr & 0x7f, temp); } - return temp; } @@ -2491,7 +2491,7 @@ xga_render_overscan_left(xga_t *xga, svga_t *svga) if (svga->scrblank || (xga->h_disp == 0)) return; - uint32_t *line_ptr = svga->monitor->target_buffer->line[xga->displine + svga->y_add]; + uint32_t *line_ptr = buffer32->line[xga->displine + svga->y_add]; for (int i = 0; i < svga->x_add; i++) *line_ptr++ = svga->overscan_color; } @@ -2507,7 +2507,7 @@ xga_render_overscan_right(xga_t *xga, svga_t *svga) if (svga->scrblank || (xga->h_disp == 0)) return; - uint32_t *line_ptr = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp]; + uint32_t *line_ptr = &buffer32->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp]; right = (overscan_x >> 1); for (int i = 0; i < right; i++) *line_ptr++ = svga->overscan_color; @@ -2524,10 +2524,11 @@ xga_render_4bpp(svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; + xga->lastline_draw = xga->displine; for (int x = 0; x <= xga->h_disp; x += 16) { @@ -2569,7 +2570,7 @@ xga_render_8bpp(svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; @@ -2607,7 +2608,7 @@ xga_render_16bpp(svga_t *svga) return; if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) { - p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add]; + p = &buffer32->line[xga->displine + svga->y_add][svga->x_add]; if (xga->firstline_draw == 2000) xga->firstline_draw = xga->displine; @@ -2635,17 +2636,51 @@ xga_render_16bpp(svga_t *svga) } } +void +xga_write_test(uint32_t addr, uint8_t val, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + + if (xga_active && xga) { + if (((xga->op_mode & 7) >= 1) && (xga->aperture_cntl >= 1)) { + if (val == 0xa5) { /*Memory size test of XGA*/ + xga->test = val; + if (addr == 0xa0001) + xga->a5_test = 1; + else if (addr == 0xafffe) + xga->a5_test = 2; + + xga->on = 0; + vga_on = 1; + xga->disp_cntl_2 = 0; + xga_log("XGA test1 addr=%05x, test=%02x.\n", addr, xga->a5_test); + } else if (val == 0x5a) { + xga->test = val; + xga->on = 0; + vga_on = 1; + xga->disp_cntl_2 = 0; + xga_log("XGA test2 addr = %05x.\n", addr); + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { + addr += xga->write_bank; + xga->vram[addr & xga->vram_mask] = val; + xga_log("XGA Linear endian reverse write, val = %02x, addr = %05x, banked mask = %04x, a5test=%d.\n", val, addr, svga->banked_mask, xga->a5_test); + if (!xga->a5_test) + xga->linear_endian_reverse = 1; + } + } else { + xga->on = 0; + vga_on = 1; + } + } +} + static void xga_write(uint32_t addr, uint8_t val, void *priv) { svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - if (!xga->on) { - svga_write(addr, val, svga); - return; - } - addr &= xga->banked_mask; addr += xga->write_bank; @@ -2667,12 +2702,6 @@ static void xga_writew(uint32_t addr, uint16_t val, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; - - if (!xga->on) { - svga_writew(addr, val, svga); - return; - } xga_write(addr, val & 0xff, svga); xga_write(addr + 1, val >> 8, svga); @@ -2682,12 +2711,6 @@ static void xga_writel(uint32_t addr, uint32_t val, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; - - if (!xga->on) { - svga_writel(addr, val, svga); - return; - } xga_write(addr, val & 0xff, svga); xga_write(addr + 1, (val >> 8) & 0xff, svga); @@ -2695,6 +2718,49 @@ xga_writel(uint32_t addr, uint32_t val, void *priv) xga_write(addr + 3, (val >> 24) & 0xff, svga); } +uint8_t +xga_read_test(uint32_t addr, void *priv) +{ + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; + uint8_t ret = 0x00; + + if (xga_active && xga) { + if (((xga->op_mode & 7) >= 1) && (xga->aperture_cntl >= 1)) { + if (xga->test == 0xa5) { /*Memory size test of XGA*/ + if (addr == 0xa0001) { + ret = xga->test; + xga->on = 1; + vga_on = 0; + } else if ((addr == 0xa0000) && (xga->a5_test == 1)) { /*This is required by XGAKIT to pass the memory test*/ + xga_log("A5 test bank = %x.\n", addr); + addr += xga->read_bank; + ret = xga->vram[addr & xga->vram_mask]; + } else { + ret = xga->test; + xga->on = 1; + vga_on = 0; + } + xga_log("A5 read: XGA ON = %d, addr = %05x, ret = %02x, test1 = %x.\n", xga->on, addr, ret, xga->a5_test); + return ret; + } else if (xga->test == 0x5a) { + ret = xga->test; + xga->on = 1; + vga_on = 0; + xga_log("5A read: XGA ON = %d.\n", xga->on); + return ret; + } else if ((addr == 0xa0000) || (addr == 0xa0010)) { + addr += xga->read_bank; + return xga->vram[addr & xga->vram_mask]; + } + } else { + xga->on = 0; + vga_on = 1; + } + } + return ret; +} + static uint8_t xga_read(uint32_t addr, void *priv) { @@ -2702,16 +2768,13 @@ xga_read(uint32_t addr, void *priv) xga_t *xga = (xga_t *) svga->xga; uint8_t ret = 0xff; - if (!xga->on) { - ret = svga_read(addr, svga); - return ret; - } - addr &= xga->banked_mask; addr += xga->read_bank; - if (addr >= xga->vram_size) + if (addr >= xga->vram_size) { + xga_log("Over Read ADDR=%x.\n", addr); return ret; + } cycles -= svga->monitor->mon_video_timing_read_b; @@ -2729,14 +2792,8 @@ static uint16_t xga_readw(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint16_t ret = 0xffff; - if (!xga->on) { - ret = svga_readw(addr, svga); - return ret; - } - ret = xga_read(addr, svga); ret |= (xga_read(addr + 1, svga) << 8); @@ -2747,14 +2804,8 @@ static uint32_t xga_readl(uint32_t addr, void *priv) { svga_t *svga = (svga_t *) priv; - xga_t *xga = (xga_t *) svga->xga; uint32_t ret = 0xffffffff; - if (!xga->on) { - ret = svga_readl(addr, svga); - return ret; - } - ret = xga_read(addr, svga); ret |= (xga_read(addr + 1, svga) << 8); ret |= (xga_read(addr + 2, svga) << 16); @@ -2774,10 +2825,12 @@ xga_write_linear(uint32_t addr, uint8_t val, void *priv) return; } - addr &= svga->decode_mask; + addr &= (xga->vram_size - 1); - if (addr >= xga->vram_size) + if (addr >= xga->vram_size) { + xga_log("Write Linear Over!.\n"); return; + } cycles -= svga->monitor->mon_video_timing_write_b; @@ -2837,10 +2890,12 @@ xga_read_linear(uint32_t addr, void *priv) if (!xga->on) return svga_read_linear(addr, svga); - addr &= svga->decode_mask; + addr &= (xga->vram_size - 1); - if (addr >= xga->vram_size) + if (addr >= xga->vram_size) { + xga_log("Read Linear Over ADDR=%x!.\n", addr); return ret; + } cycles -= svga->monitor->mon_video_timing_read_b; @@ -2891,43 +2946,11 @@ xga_readl_linear(uint32_t addr, void *priv) return ret; } -static void -xga_do_render(svga_t *svga) -{ - xga_t *xga = (xga_t *) svga->xga; - - xga_log("DISPCNTL = %d, vga = %d.\n", xga->disp_cntl_2 & 7, vga_on); - switch (xga->disp_cntl_2 & 7) { - case 2: - xga_render_4bpp(svga); - break; - case 3: - xga_render_8bpp(svga); - break; - case 4: - xga_render_16bpp(svga); - break; - default: - break; - } - - svga->x_add = (overscan_x >> 1); - xga_render_overscan_left(xga, svga); - xga_render_overscan_right(xga, svga); - svga->x_add = (overscan_x >> 1); - - if (xga->hwcursor_on) { - xga_hwcursor_draw(svga, xga->displine + svga->y_add); - xga->hwcursor_on--; - if (xga->hwcursor_on && xga->interlace) - xga->hwcursor_on--; - } -} - void -xga_poll(void *priv, svga_t *svga) +xga_poll(void *priv) { - xga_t *xga = (xga_t *) priv; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; uint32_t x; int wx; int wy; @@ -2944,6 +2967,7 @@ xga_poll(void *priv, svga_t *svga) } timer_advance_u64(&svga->timer, svga->dispofftime); + svga->cgastat |= 1; xga->linepos = 1; if (xga->dispon) { @@ -2959,7 +2983,32 @@ xga_poll(void *priv, svga_t *svga) if (xga->hwcursor_on) xga->changedvram[xga->ma >> 12] = xga->changedvram[(xga->ma >> 12) + 1] = xga->interlace ? 3 : 2; - xga_do_render(svga); + xga_log("DISPCNTL = %d, vga = %d.\n", xga->disp_cntl_2 & 7, vga_on); + switch (xga->disp_cntl_2 & 7) { + case 2: + xga_render_4bpp(svga); + break; + case 3: + xga_render_8bpp(svga); + break; + case 4: + xga_render_16bpp(svga); + break; + default: + break; + } + + svga->x_add = (overscan_x >> 1); + xga_render_overscan_left(xga, svga); + xga_render_overscan_right(xga, svga); + svga->x_add = (overscan_x >> 1); + + if (xga->hwcursor_on) { + xga_hwcursor_draw(svga, xga->displine + svga->y_add); + xga->hwcursor_on--; + if (xga->hwcursor_on && xga->interlace) + xga->hwcursor_on--; + } if (xga->lastline < xga->displine) xga->lastline = xga->displine; @@ -2968,10 +3017,15 @@ xga_poll(void *priv, svga_t *svga) xga->displine++; if (xga->interlace) xga->displine++; + if ((svga->cgastat & 8) && ((xga->displine & 0x0f) == (svga->crtc[0x11] & 0x0f)) && svga->vslines) + svga->cgastat &= ~8; if (xga->displine > 1500) xga->displine = 0; } else { timer_advance_u64(&svga->timer, svga->dispontime); + if (xga->dispon) + svga->cgastat &= ~1; + xga->h_disp_on = 0; xga->linepos = 0; @@ -2979,6 +3033,7 @@ xga_poll(void *priv, svga_t *svga) if (xga->sc == xga->rowcount) { xga->sc = 0; + xga_log("MA=%08x, MALATCH=%x.\n", xga->ma, xga->ma_latch); xga->maback += (xga->rowoffset << 3); if (xga->interlace) xga->maback += (xga->rowoffset << 3); @@ -3018,6 +3073,7 @@ xga_poll(void *priv, svga_t *svga) } if (xga->vc == xga->v_syncstart) { xga->dispon = 0; + svga->cgastat |= 8; x = xga->h_disp; if (xga->interlace && !xga->oddeven) @@ -3065,13 +3121,10 @@ xga_poll(void *priv, svga_t *svga) static uint8_t xga_mca_read(int port, void *priv) { - const svga_t *svga = (svga_t *) priv; - const xga_t *xga = (xga_t *) svga->xga; + svga_t *svga = (svga_t *) priv; + xga_t *xga = (xga_t *) svga->xga; uint8_t ret = xga->pos_regs[port & 7]; - if (((port & 7) == 3) && !(ret & 1)) /*Always enable the mapping.*/ - ret |= 1; - xga_log("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, port & 7, xga->pos_regs[port & 7]); @@ -3089,7 +3142,6 @@ xga_mca_write(int port, uint8_t val, void *priv) return; io_removehandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - mem_mapping_disable(&xga->bios_rom.mapping); mem_mapping_disable(&xga->memio_mapping); xga->on = 0; vga_on = 1; @@ -3098,8 +3150,6 @@ xga_mca_write(int port, uint8_t val, void *priv) /* Save the MCA register value. */ xga->pos_regs[port & 7] = val; - if (!(xga->pos_regs[4] & 1) && (mem_size >= 16384)) /*MCA 4MB addressing on systems with more than 16MB of memory*/ - xga->pos_regs[4] |= 1; if (xga->pos_regs[2] & 1) { xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; @@ -3109,10 +3159,10 @@ xga_mca_write(int port, uint8_t val, void *priv) io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - if (xga->pos_regs[3] & 1) - mem_mapping_set_addr(&xga->bios_rom.mapping, xga->rom_addr, 0x2000); - else - mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); + if (xga->rom_addr) { + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x2000); + xga_log("ROM address=%05x.\n", xga->rom_addr); + } } xga_log("[%04X:%08X]: POS Write Port = %x, val = %02x, linear base = %08x, instance = %d, " @@ -3126,6 +3176,7 @@ xga_mca_feedb(void *priv) const svga_t *svga = (svga_t *) priv; const xga_t *xga = (xga_t *) svga->xga; + xga_log("FeedB.\n"); return xga->pos_regs[2] & 1; } @@ -3135,10 +3186,10 @@ xga_mca_reset(void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - mem_mapping_disable(&xga->bios_rom.mapping); mem_mapping_disable(&xga->memio_mapping); xga->on = 0; vga_on = 1; + xga_log("MCA Reset.\n"); xga_mca_write(0x102, 0, svga); xga->linear_endian_reverse = 0; xga->a5_test = 0; @@ -3150,8 +3201,10 @@ xga_reset(void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - mem_mapping_disable(&xga->bios_rom.mapping); - mem_mapping_disable(&xga->memio_mapping); + xga_log("Normal Reset.\n"); + if (xga_standalone_enabled) + mem_mapping_disable(&xga->memio_mapping); + xga->on = 0; vga_on = 1; xga->linear_endian_reverse = 0; @@ -3163,32 +3216,31 @@ xga_pos_in(uint16_t addr, void *priv) { svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; - uint8_t ret = 0xff; + uint8_t ret = 0x00; if (!xga_standalone_enabled) { switch (addr) { case 0x0100: case 0x0101: - if (xga->instance_isa == xga->instance_num) + if (xga->instance == xga->instance_num) ret = xga->pos_regs[addr & 7]; else ret = 0xff; + + xga_log("%03xRead=%02x.\n", addr, ret); break; case 0x0102: - case 0x0105: - ret = xga->pos_regs[addr & 7]; + ret = xga->pos_regs[2] | 0x30; break; - case 0x0106: - ret = xga->pos_idx >> 8; - break; - case 0x0107: - ret = xga->pos_idx & 0xff; + case 0x0105: + ret = xga->pos_regs[5]; + xga_log("POS IDX Read 010%x ret = %02x.\n", addr & 7, ret); break; case 0x0103: - if (!(xga->pos_idx & 3)) + if ((xga->pos_idx & 3) == 0) { ret = xga->pos_regs[3]; - else - ret = 0; + ret |= (xga->dma_channel << 3); + } xga_log("POS IDX for 0103 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); break; @@ -3203,31 +3255,25 @@ xga_pos_in(uint16_t addr, void *priv) case 2: ret = xga->pos_regs[1]; break; - case 3: - ret = 0; - break; default: break; } - xga_log("POS IDX for 0104 = %d, ret = %02x.\n", xga->pos_idx & 3, ret); break; - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; - if (xga->instance_isa == xga->instance_num) - ret = xga->instance_isa; - else - ret = 0; + case 0x0106: + ret = xga->pos_idx >> 8; + break; + case 0x0107: + ret = xga->pos_idx & 0xff; + break; + case 0x0108 ... 0x010f: + xga->instance_num = addr & 0x07; + if (xga->instance == xga->instance_num) + ret = xga->instance; ret |= xga->isa_pos_enable; + xga_log("%03xRead=%02x.\n", addr, ret); break; default: @@ -3235,12 +3281,15 @@ xga_pos_in(uint16_t addr, void *priv) } } else { switch (addr) { + case 0x0096: + ret = xga->vga_post; + break; case 0x0100: case 0x0101: ret = xga->pos_regs[addr & 7]; break; case 0x0103: - ret = xga->pos_regs[3] | 7; + ret = xga->pos_regs[3] | 0x06; ret |= (xga->dma_channel << 3); break; case 0x0102: @@ -3250,27 +3299,12 @@ xga_pos_in(uint16_t addr, void *priv) case 0x0107: ret = (xga_mca_read(addr, svga)); break; - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; - if (xga->instance_isa == xga->instance_num) - ret = xga->instance_isa; - else - ret = 0; - - ret |= xga->isa_pos_enable; - break; default: break; } } + xga_log("[%04X:%08X]: XGA POS IN addr=%04x, ret=%02x.\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -3280,8 +3314,44 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) svga_t *svga = (svga_t *) priv; xga_t *xga = (xga_t *) svga->xga; + xga_log("[%04X:%08X]: XGA POS OUT addr=%04x, val=%02x.\n", CS, cpu_state.pc, addr, val); if (!xga_standalone_enabled) { switch (addr) { + case 0x0096: + xga->instance_num = val & 0x07; + xga->isa_pos_enable = val & 0x08; + xga_log("096Write=%02x.\n", val); + break; + case 0x0102: + xga_log("[%04X:%08X]: 102Write=%02x.\n", CS, cpu_state.pc, val); + xga->pos_regs[2] = val | 0x02; /*Instance 0 is not recommended on AT bus/ISA bus systems, so force it to use instance 1.*/ + io_removehandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + mem_mapping_disable(&xga->memio_mapping); + if (xga->pos_regs[2] & 0x01) { + xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xc0) >> 6) * 0x8000); + xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; + xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); + xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; + io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + xga_log("XGA ISA ROM address=%05x, instance=%d.\n", xga->rom_addr, xga->instance); + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x8000); + } + break; + case 0x0103: + if ((xga->pos_idx & 3) == 0) + xga->pos_regs[3] = val; + + xga_log("[%04X:%08X]: 103Write=%02x.\n", CS, cpu_state.pc, val); + break; + case 0x0104: + xga_log("104Write=%02x.\n", val); + if ((xga->pos_idx & 3) == 0) + xga->pos_regs[4] = val; + break; + case 0x0105: + xga_log("105Write=%02x.\n", val); + xga->pos_regs[5] = val; + break; case 0x0106: xga->pos_idx = (xga->pos_idx & 0x00ff) | (val << 8); break; @@ -3289,15 +3359,9 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) xga->pos_idx = (xga->pos_idx & 0xff00) | val; xga_log("POS IDX Write = %04x.\n", xga->pos_idx); break; - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; + case 0x0108 ... 0x010f: + xga_log("%03xWrite=%02x.\n", addr, val); + xga->instance_num = addr & 0x07; xga->isa_pos_enable = val & 0x08; break; @@ -3305,17 +3369,10 @@ xga_pos_out(uint16_t addr, uint8_t val, void *priv) break; } } else { + xga_log("XGA Standalone ISA Write Port=%04x, Val=%02x.\n", addr, val); switch (addr) { - case 0x0108: - case 0x0109: - case 0x010a: - case 0x010b: - case 0x010c: - case 0x010d: - case 0x010e: - case 0x010f: - xga->instance_num = addr & 7; - xga->isa_pos_enable = val & 0x08; + case 0x0096: + xga->vga_post = val; break; default: @@ -3332,8 +3389,6 @@ xga_init(const device_t *info) svga_t *svga = svga_get_pri(); xga_t *xga = (xga_t *) calloc(1, sizeof(xga_t)); - FILE *fp; - uint8_t *rom = NULL; svga->xga = xga; @@ -3346,47 +3401,53 @@ xga_init(const device_t *info) xga->vram_size = (1024 << 10); xga->vram_mask = xga->vram_size - 1; xga->vram = calloc(xga->vram_size, 1); - xga->changedvram = calloc(xga->vram_size >> 12, 1); + xga->changedvram = calloc((xga->vram_size >> 12) + 1, 1); xga->on = 0; xga->hwcursor.cur_xsize = 64; xga->hwcursor.cur_ysize = 64; - xga->bios_rom.sz = 0x2000; xga->linear_endian_reverse = 0; xga->a5_test = 0; - fp = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb"); - (void) fseek(fp, 0L, SEEK_END); - (void) fseek(fp, 0L, SEEK_SET); - - rom = malloc(xga->bios_rom.sz); - memset(rom, 0xff, xga->bios_rom.sz); - (void) !fread(rom, xga->bios_rom.sz, 1, fp); - (void) fclose(fp); - - xga->bios_rom.rom = rom; - xga->bios_rom.mask = xga->bios_rom.sz - 1; - if (fp != NULL) { - free(rom); - } - - xga->base_addr_1mb = 0; if (info->flags & DEVICE_MCA) { video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_mca); + xga->base_addr_1mb = 0; xga->linear_base = 0; xga->instance = 0; xga->rom_addr = 0; rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&xga->bios_rom.mapping); + mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, + xga_memio_writeb, xga_memio_writew, xga_memio_writel, + xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); } else { - if (!xga_standalone_enabled) - rom_init(&xga->vga_bios_rom, INMOS_XGA_BIOS_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - else - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa); - - xga->pos_regs[2] = 1 | (xga->instance_isa << 1) | xga->ext_mem_addr; - xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; - xga->pos_regs[4] = 1 | 2; - xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); - xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + xga->pos_regs[4] = 0x02; + if (!xga_standalone_enabled) { + rom_init(&xga->bios_rom, INMOS_XGA_BIOS_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); /*VGA BIOS only*/ + mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, + xga_memio_writeb, xga_memio_writew, xga_memio_writel, + xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); + } else { + xga->pos_regs[2] = (xga->instance_isa << 1) | xga->ext_mem_addr; + xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000); + xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; + xga->pos_regs[2] |= 0x01; + if (mem_size >= 16384) { + xga->pos_regs[4] |= 0x01; + xga->pos_regs[5] = 0; + } else { + xga->pos_regs[5] = ((mem_size * 64) >> 0x10) + 1; + if (xga->pos_regs[5] == 0x10) { + xga->pos_regs[5] = 0x00; + xga->pos_regs[4] |= 0x01; + } + } + xga->base_addr_1mb = (xga->pos_regs[5] & 0x0f) << 20; + xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22); + rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, xga->rom_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, + xga_memio_writeb, xga_memio_writew, xga_memio_writel, + xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); + } } mem_mapping_add(&xga->video_mapping, 0, 0, xga_read, xga_readw, xga_readl, @@ -3395,9 +3456,6 @@ xga_init(const device_t *info) mem_mapping_add(&xga->linear_mapping, 0, 0, xga_read_linear, xga_readw_linear, xga_readl_linear, xga_write_linear, xga_writew_linear, xga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga); - mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl, - xga_memio_writeb, xga_memio_writew, xga_memio_writel, - !xga_standalone_enabled ? xga->vga_bios_rom.rom : xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga); mem_mapping_disable(&xga->linear_mapping); mem_mapping_disable(&xga->memio_mapping); @@ -3408,13 +3466,12 @@ xga_init(const device_t *info) if (xga->bus & DEVICE_MCA) { mca_add(xga_mca_read, xga_mca_write, xga_mca_feedb, xga_mca_reset, svga); } else { - io_sethandler(0x0100, 0x0008, xga_pos_in, NULL, NULL, NULL, NULL, NULL, svga); - if (!xga_standalone_enabled) - io_sethandler(0x0106, 0x0002, NULL, NULL, NULL, xga_pos_out, NULL, NULL, svga); - - io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - io_sethandler(0x0108, 0x0008, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); - mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); + io_sethandler(0x0096, 0x0001, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); + io_sethandler(0x0100, 0x0010, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga); + if (xga_standalone_enabled) { + io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); + mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr, 0x2000); + } } return svga; } @@ -3594,6 +3651,47 @@ static const device_config_t xga_isa_configuration[] = { // clang-format on }; +static const device_config_t xga_inmos_isa_configuration[] = { + // clang-format off + { + .name = "type", + .description = "XGA type", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 0, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { + .description = "XGA-1", + .value = 0 + }, + { + .description = "XGA-2", + .value = 1 + }, + { .description = "" } + } + }, + { + .name = "dma", + .description = "DMA channel", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 7, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Disabled", .value = 0 }, + { .description = "DMA 6", .value = 6 }, + { .description = "DMA 7", .value = 7 }, + { .description = "" } + }, + }, + { .name = "", .description = "", .type = CONFIG_END } + // clang-format on +}; + const device_t xga_device = { .name = "XGA (MCA)", .internal_name = "xga_mca", @@ -3633,7 +3731,7 @@ const device_t inmos_isa_device = { { .available = inmos_xga_available }, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, - .config = xga_isa_configuration + .config = xga_inmos_isa_configuration }; void diff --git a/vcpkg.json b/vcpkg.json index d9ea83dba7..af6f9a5c8f 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "86box", - "version-string": "4.2", + "version-string": "4.2.2", "homepage": "https://86box.net/", "documentation": "https://86box.readthedocs.io/", "license": "GPL-2.0-or-later",